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 << this << ": ";
395     s->Indent();
396     s->PutCString("SymbolContext");
397     s->IndentMore();
398     s->EOL();
399     s->IndentMore();
400     s->Indent();
401     *s << "Module       = " << module_sp.get() << ' ';
402     if (module_sp)
403         module_sp->GetFileSpec().Dump(s);
404     s->EOL();
405     s->Indent();
406     *s << "CompileUnit  = " << 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     = " << 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        = " << 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       = " << symbol;
440     if (symbol != nullptr && symbol->GetMangled())
441         *s << ' ' << symbol->GetName().AsCString();
442     s->EOL();
443     *s << "Variable     = " << 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 LanguageType
529 SymbolContext::GetLanguage () const
530 {
531     LanguageType lang;
532     if (function &&
533         (lang = function->GetLanguage()) != eLanguageTypeUnknown)
534     {
535         return lang;
536     }
537     else if (variable &&
538              (lang = variable->GetLanguage()) != eLanguageTypeUnknown)
539     {
540         return lang;
541     }
542     else if (symbol &&
543              (lang = symbol->GetLanguage()) != eLanguageTypeUnknown)
544     {
545         return lang;
546     }
547     else if (comp_unit &&
548              (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown)
549     {
550         return lang;
551     }
552     else if (symbol)
553     {
554         // If all else fails, try to guess the language from the name.
555         return symbol->GetMangled().GuessLanguage();
556     }
557     return eLanguageTypeUnknown;
558 }
559 
560 bool
561 SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
562                                         SymbolContext &next_frame_sc,
563                                         Address &next_frame_pc) const
564 {
565     next_frame_sc.Clear(false);
566     next_frame_pc.Clear();
567 
568     if (block)
569     {
570         //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
571 
572         // In order to get the parent of an inlined function we first need to
573         // see if we are in an inlined block as "this->block" could be an
574         // inlined block, or a parent of "block" could be. So lets check if
575         // this block or one of this blocks parents is an inlined function.
576         Block *curr_inlined_block = block->GetContainingInlinedBlock();
577         if (curr_inlined_block)
578         {
579             // "this->block" is contained in an inline function block, so to
580             // get the scope above the inlined block, we get the parent of the
581             // inlined block itself
582             Block *next_frame_block = curr_inlined_block->GetParent();
583             // Now calculate the symbol context of the containing block
584             next_frame_block->CalculateSymbolContext (&next_frame_sc);
585 
586             // If we get here we weren't able to find the return line entry using the nesting of the blocks and
587             // the line table.  So just use the call site info from our inlined block.
588 
589             AddressRange range;
590             if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
591             {
592                 // To see there this new frame block it, we need to look at the
593                 // call site information from
594                 const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
595                 next_frame_pc = range.GetBaseAddress();
596                 next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
597                 next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
598                 next_frame_sc.line_entry.original_file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
599                 next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
600                 next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
601                 return true;
602             }
603             else
604             {
605                 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
606 
607                 if (log)
608                 {
609                     log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
610                                  curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
611                 }
612 #ifdef LLDB_CONFIGURATION_DEBUG
613                 else
614                 {
615                     ObjectFile *objfile = NULL;
616                     if (module_sp)
617                     {
618                         SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
619                         if (symbol_vendor)
620                         {
621                             SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
622                             if (symbol_file)
623                                 objfile = symbol_file->GetObjectFile();
624                         }
625                     }
626                     if (objfile)
627                     {
628                         Host::SystemLog (Host::eSystemLogWarning,
629                                          "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
630                                          curr_inlined_block->GetID(),
631                                          curr_frame_pc.GetFileAddress(),
632                                          objfile->GetFileSpec().GetPath().c_str());
633                     }
634                     else
635                     {
636                         Host::SystemLog (Host::eSystemLogWarning,
637                                          "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
638                                          curr_inlined_block->GetID(),
639                                          curr_frame_pc.GetFileAddress());
640                     }
641                 }
642 #endif
643             }
644         }
645     }
646 
647     return false;
648 }
649 
650 Block *
651 SymbolContext::GetFunctionBlock ()
652 {
653     if (function)
654     {
655         if (block)
656         {
657             // If this symbol context has a block, check to see if this block
658             // is itself, or is contained within a block with inlined function
659             // information. If so, then the inlined block is the block that
660             // defines the function.
661             Block *inlined_block = block->GetContainingInlinedBlock();
662             if (inlined_block)
663                 return inlined_block;
664 
665             // The block in this symbol context is not inside an inlined
666             // block, so the block that defines the function is the function's
667             // top level block, which is returned below.
668         }
669 
670         // There is no block information in this symbol context, so we must
671         // assume that the block that is desired is the top level block of
672         // the function itself.
673         return &function->GetBlock(true);
674     }
675     return nullptr;
676 }
677 
678 bool
679 SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
680                                       bool &is_instance_method,
681                                       ConstString &language_object_name)
682 
683 
684 {
685     Block *function_block = GetFunctionBlock();
686     if (function_block)
687     {
688         CompilerDeclContext decl_ctx = function_block->GetDeclContext();
689         if (decl_ctx)
690             return decl_ctx.IsClassMethod(&language, &is_instance_method, &language_object_name);
691     }
692     return false;
693 }
694 
695 void
696 SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const
697 {
698     Block * curr_block = block;
699     bool isInlinedblock = false;
700     if (curr_block != nullptr && curr_block->GetContainingInlinedBlock() != nullptr)
701         isInlinedblock = true;
702 
703     //----------------------------------------------------------------------
704     // Find all types that match the current block if we have one and put
705     // them first in the list. Keep iterating up through all blocks.
706     //----------------------------------------------------------------------
707     while (curr_block != nullptr && !isInlinedblock)
708     {
709         type_map.ForEach([curr_block, &type_list](const lldb::TypeSP& type_sp) -> bool {
710             SymbolContextScope *scs = type_sp->GetSymbolContextScope();
711             if (scs && curr_block == scs->CalculateSymbolContextBlock())
712                 type_list.Insert(type_sp);
713             return true; // Keep iterating
714         });
715 
716         // Remove any entries that are now in "type_list" from "type_map"
717         // since we can't remove from type_map while iterating
718         type_list.ForEach([&type_map](const lldb::TypeSP& type_sp) -> bool {
719             type_map.Remove(type_sp);
720             return true; // Keep iterating
721         });
722         curr_block = curr_block->GetParent();
723     }
724     //----------------------------------------------------------------------
725     // Find all types that match the current function, if we have onem, and
726     // put them next in the list.
727     //----------------------------------------------------------------------
728     if (function != nullptr && !type_map.Empty())
729     {
730         const size_t old_type_list_size = type_list.GetSize();
731         type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
732             SymbolContextScope *scs = type_sp->GetSymbolContextScope();
733             if (scs && function == scs->CalculateSymbolContextFunction())
734                 type_list.Insert(type_sp);
735             return true; // Keep iterating
736         });
737 
738         // Remove any entries that are now in "type_list" from "type_map"
739         // since we can't remove from type_map while iterating
740         const size_t new_type_list_size = type_list.GetSize();
741         if (new_type_list_size > old_type_list_size)
742         {
743             for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
744                 type_map.Remove(type_list.GetTypeAtIndex(i));
745         }
746     }
747     //----------------------------------------------------------------------
748     // Find all types that match the current compile unit, if we have one,
749     // and put them next in the list.
750     //----------------------------------------------------------------------
751     if (comp_unit != nullptr && !type_map.Empty())
752     {
753         const size_t old_type_list_size = type_list.GetSize();
754 
755         type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
756             SymbolContextScope *scs = type_sp->GetSymbolContextScope();
757             if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())
758                 type_list.Insert(type_sp);
759             return true; // Keep iterating
760         });
761 
762         // Remove any entries that are now in "type_list" from "type_map"
763         // since we can't remove from type_map while iterating
764         const size_t new_type_list_size = type_list.GetSize();
765         if (new_type_list_size > old_type_list_size)
766         {
767             for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
768                 type_map.Remove(type_list.GetTypeAtIndex(i));
769         }
770     }
771     //----------------------------------------------------------------------
772     // Find all types that match the current module, if we have one, and put
773     // them next in the list.
774     //----------------------------------------------------------------------
775     if (module_sp && !type_map.Empty())
776     {
777         const size_t old_type_list_size = type_list.GetSize();
778         type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
779             SymbolContextScope *scs = type_sp->GetSymbolContextScope();
780             if (scs &&  module_sp == scs->CalculateSymbolContextModule())
781                 type_list.Insert(type_sp);
782             return true; // Keep iterating
783         });
784         // Remove any entries that are now in "type_list" from "type_map"
785         // since we can't remove from type_map while iterating
786         const size_t new_type_list_size = type_list.GetSize();
787         if (new_type_list_size > old_type_list_size)
788         {
789             for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
790                 type_map.Remove(type_list.GetTypeAtIndex(i));
791         }
792     }
793     //----------------------------------------------------------------------
794     // Any types that are left get copied into the list an any order.
795     //----------------------------------------------------------------------
796     if (!type_map.Empty())
797     {
798         type_map.ForEach([&type_list](const lldb::TypeSP& type_sp) -> bool {
799             type_list.Insert(type_sp);
800             return true; // Keep iterating
801         });
802     }
803 }
804 
805 ConstString
806 SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
807 {
808     if (function)
809     {
810         if (block)
811         {
812             Block *inlined_block = block->GetContainingInlinedBlock();
813 
814             if (inlined_block)
815             {
816                 const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
817                 if (inline_info)
818                     return inline_info->GetName(function->GetLanguage());
819             }
820         }
821         return function->GetMangled().GetName(function->GetLanguage(), preference);
822     }
823     else if (symbol && symbol->ValueIsAddress())
824     {
825         return symbol->GetMangled().GetName(symbol->GetLanguage(), preference);
826     }
827     else
828     {
829         // No function, return an empty string.
830         return ConstString();
831     }
832 }
833 
834 LineEntry
835 SymbolContext::GetFunctionStartLineEntry () const
836 {
837     LineEntry line_entry;
838     Address start_addr;
839     if (block)
840     {
841         Block *inlined_block = block->GetContainingInlinedBlock();
842         if (inlined_block)
843         {
844             if (inlined_block->GetStartAddress (start_addr))
845             {
846                 if (start_addr.CalculateSymbolContextLineEntry (line_entry))
847                     return line_entry;
848             }
849             return LineEntry();
850         }
851     }
852 
853     if (function)
854     {
855         if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
856             return line_entry;
857     }
858     return LineEntry();
859 }
860 
861 bool
862 SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range, Error &error)
863 {
864     if (!line_entry.IsValid())
865     {
866         error.SetErrorString("Symbol context has no line table.");
867         return false;
868     }
869 
870     range = line_entry.range;
871     if (line_entry.line > end_line)
872     {
873         error.SetErrorStringWithFormat("end line option %d must be after the current line: %d",
874                                      end_line,
875                                      line_entry.line);
876         return false;
877     }
878 
879     uint32_t line_index = 0;
880     bool found = false;
881     while (1)
882     {
883         LineEntry this_line;
884         line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, false, &this_line);
885         if (line_index == UINT32_MAX)
886             break;
887         if (LineEntry::Compare(this_line, line_entry) == 0)
888         {
889             found = true;
890             break;
891         }
892     }
893 
894     LineEntry end_entry;
895     if (!found)
896     {
897         // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit.
898         error.SetErrorString("Can't find the current line entry in the CompUnit - can't process "
899                                      "the end-line option");
900         return false;
901     }
902 
903     line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false, &end_entry);
904     if (line_index == UINT32_MAX)
905     {
906         error.SetErrorStringWithFormat("could not find a line table entry corresponding "
907                                        "to end line number %d",
908                                        end_line);
909         return false;
910     }
911 
912     Block *func_block = GetFunctionBlock();
913     if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX)
914     {
915         error.SetErrorStringWithFormat("end line number %d is not contained within the current function.",
916                                      end_line);
917         return false;
918     }
919 
920     lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress()
921                               - range.GetBaseAddress().GetFileAddress();
922     range.SetByteSize(range_size);
923     return true;
924 }
925 
926 
927 
928 //----------------------------------------------------------------------
929 //
930 //  SymbolContextSpecifier
931 //
932 //----------------------------------------------------------------------
933 
934 SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
935     m_target_sp (target_sp),
936     m_module_spec (),
937     m_module_sp (),
938     m_file_spec_ap (),
939     m_start_line (0),
940     m_end_line (0),
941     m_function_spec (),
942     m_class_name (),
943     m_address_range_ap (),
944     m_type (eNothingSpecified)
945 {
946 }
947 
948 SymbolContextSpecifier::~SymbolContextSpecifier()
949 {
950 }
951 
952 bool
953 SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
954 {
955     bool return_value = true;
956     switch (type)
957     {
958     case eNothingSpecified:
959         Clear();
960         break;
961     case eLineStartSpecified:
962         m_start_line = line_no;
963         m_type |= eLineStartSpecified;
964         break;
965     case eLineEndSpecified:
966         m_end_line = line_no;
967         m_type |= eLineEndSpecified;
968         break;
969     default:
970         return_value = false;
971         break;
972     }
973     return return_value;
974 }
975 
976 bool
977 SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
978 {
979     bool return_value = true;
980     switch (type)
981     {
982     case eNothingSpecified:
983         Clear();
984         break;
985     case eModuleSpecified:
986         {
987             // See if we can find the Module, if so stick it in the SymbolContext.
988             FileSpec module_file_spec(spec_string, false);
989             ModuleSpec module_spec (module_file_spec);
990             lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
991             m_type |= eModuleSpecified;
992             if (module_sp)
993                 m_module_sp = module_sp;
994             else
995                 m_module_spec.assign (spec_string);
996         }
997         break;
998     case eFileSpecified:
999         // CompUnits can't necessarily be resolved here, since an inlined function might show up in
1000         // a number of CompUnits.  Instead we just convert to a FileSpec and store it away.
1001         m_file_spec_ap.reset (new FileSpec (spec_string, false));
1002         m_type |= eFileSpecified;
1003         break;
1004     case eLineStartSpecified:
1005         m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
1006         if (return_value)
1007             m_type |= eLineStartSpecified;
1008         break;
1009     case eLineEndSpecified:
1010         m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
1011         if (return_value)
1012             m_type |= eLineEndSpecified;
1013         break;
1014     case eFunctionSpecified:
1015         m_function_spec.assign(spec_string);
1016         m_type |= eFunctionSpecified;
1017         break;
1018     case eClassOrNamespaceSpecified:
1019         Clear();
1020         m_class_name.assign (spec_string);
1021         m_type = eClassOrNamespaceSpecified;
1022         break;
1023     case eAddressRangeSpecified:
1024         // Not specified yet...
1025         break;
1026     }
1027 
1028     return return_value;
1029 }
1030 
1031 void
1032 SymbolContextSpecifier::Clear()
1033 {
1034     m_module_spec.clear();
1035     m_file_spec_ap.reset();
1036     m_function_spec.clear();
1037     m_class_name.clear();
1038     m_start_line = 0;
1039     m_end_line = 0;
1040     m_address_range_ap.reset();
1041 
1042     m_type = eNothingSpecified;
1043 }
1044 
1045 bool
1046 SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
1047 {
1048     if (m_type == eNothingSpecified)
1049         return true;
1050 
1051     if (m_target_sp.get() != sc.target_sp.get())
1052         return false;
1053 
1054     if (m_type & eModuleSpecified)
1055     {
1056         if (sc.module_sp)
1057         {
1058             if (m_module_sp.get() != nullptr)
1059             {
1060                 if (m_module_sp.get() != sc.module_sp.get())
1061                     return false;
1062             }
1063             else
1064             {
1065                 FileSpec module_file_spec (m_module_spec.c_str(), false);
1066                 if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
1067                     return false;
1068             }
1069         }
1070     }
1071     if (m_type & eFileSpecified)
1072     {
1073         if (m_file_spec_ap.get())
1074         {
1075             // If we don't have a block or a comp_unit, then we aren't going to match a source file.
1076             if (sc.block == nullptr && sc.comp_unit == nullptr)
1077                 return false;
1078 
1079             // Check if the block is present, and if so is it inlined:
1080             bool was_inlined = false;
1081             if (sc.block != nullptr)
1082             {
1083                 const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
1084                 if (inline_info != nullptr)
1085                 {
1086                     was_inlined = true;
1087                     if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
1088                         return false;
1089                 }
1090             }
1091 
1092             // Next check the comp unit, but only if the SymbolContext was not inlined.
1093             if (!was_inlined && sc.comp_unit != nullptr)
1094             {
1095                 if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
1096                     return false;
1097             }
1098         }
1099     }
1100     if (m_type & eLineStartSpecified
1101         || m_type & eLineEndSpecified)
1102     {
1103         if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
1104             return false;
1105     }
1106 
1107     if (m_type & eFunctionSpecified)
1108     {
1109         // First check the current block, and if it is inlined, get the inlined function name:
1110         bool was_inlined = false;
1111         ConstString func_name(m_function_spec.c_str());
1112 
1113         if (sc.block != nullptr)
1114         {
1115             const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
1116             if (inline_info != nullptr)
1117             {
1118                 was_inlined = true;
1119                 const Mangled &name = inline_info->GetMangled();
1120                 if (!name.NameMatches (func_name, sc.function->GetLanguage()))
1121                     return false;
1122             }
1123         }
1124         //  If it wasn't inlined, check the name in the function or symbol:
1125         if (!was_inlined)
1126         {
1127             if (sc.function != nullptr)
1128             {
1129                 if (!sc.function->GetMangled().NameMatches(func_name, sc.function->GetLanguage()))
1130                     return false;
1131             }
1132             else if (sc.symbol != nullptr)
1133             {
1134                 if (!sc.symbol->GetMangled().NameMatches(func_name, sc.symbol->GetLanguage()))
1135                     return false;
1136             }
1137         }
1138 
1139 
1140     }
1141 
1142     return true;
1143 }
1144 
1145 bool
1146 SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
1147 {
1148     if (m_type & eAddressRangeSpecified)
1149     {
1150 
1151     }
1152     else
1153     {
1154         Address match_address (addr, nullptr);
1155         SymbolContext sc;
1156         m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
1157         return SymbolContextMatches(sc);
1158     }
1159     return true;
1160 }
1161 
1162 void
1163 SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
1164 {
1165     char path_str[PATH_MAX + 1];
1166 
1167     if (m_type == eNothingSpecified)
1168     {
1169         s->Printf ("Nothing specified.\n");
1170     }
1171 
1172     if (m_type == eModuleSpecified)
1173     {
1174         s->Indent();
1175         if (m_module_sp)
1176         {
1177             m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
1178             s->Printf ("Module: %s\n", path_str);
1179         }
1180         else
1181             s->Printf ("Module: %s\n", m_module_spec.c_str());
1182     }
1183 
1184     if (m_type == eFileSpecified  && m_file_spec_ap.get() != nullptr)
1185     {
1186         m_file_spec_ap->GetPath (path_str, PATH_MAX);
1187         s->Indent();
1188         s->Printf ("File: %s", path_str);
1189         if (m_type == eLineStartSpecified)
1190         {
1191             s->Printf (" from line %" PRIu64 "", (uint64_t)m_start_line);
1192             if (m_type == eLineEndSpecified)
1193                 s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
1194             else
1195                 s->Printf ("to end");
1196         }
1197         else if (m_type == eLineEndSpecified)
1198         {
1199             s->Printf (" from start to line %" PRIu64 "", (uint64_t)m_end_line);
1200         }
1201         s->Printf (".\n");
1202     }
1203 
1204     if (m_type == eLineStartSpecified)
1205     {
1206         s->Indent();
1207         s->Printf ("From line %" PRIu64 "", (uint64_t)m_start_line);
1208         if (m_type == eLineEndSpecified)
1209             s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line);
1210         else
1211             s->Printf ("to end");
1212         s->Printf (".\n");
1213     }
1214     else if (m_type == eLineEndSpecified)
1215     {
1216         s->Printf ("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
1217     }
1218 
1219     if (m_type == eFunctionSpecified)
1220     {
1221         s->Indent();
1222         s->Printf ("Function: %s.\n", m_function_spec.c_str());
1223     }
1224 
1225     if (m_type == eClassOrNamespaceSpecified)
1226     {
1227         s->Indent();
1228         s->Printf ("Class name: %s.\n", m_class_name.c_str());
1229     }
1230 
1231     if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr)
1232     {
1233         s->Indent();
1234         s->PutCString ("Address range: ");
1235         m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
1236         s->PutCString ("\n");
1237     }
1238 }
1239 
1240 //----------------------------------------------------------------------
1241 //
1242 //  SymbolContextList
1243 //
1244 //----------------------------------------------------------------------
1245 
1246 
1247 SymbolContextList::SymbolContextList() :
1248     m_symbol_contexts()
1249 {
1250 }
1251 
1252 SymbolContextList::~SymbolContextList()
1253 {
1254 }
1255 
1256 void
1257 SymbolContextList::Append(const SymbolContext& sc)
1258 {
1259     m_symbol_contexts.push_back(sc);
1260 }
1261 
1262 void
1263 SymbolContextList::Append (const SymbolContextList& sc_list)
1264 {
1265     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1266     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1267         m_symbol_contexts.push_back (*pos);
1268 }
1269 
1270 
1271 uint32_t
1272 SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
1273 {
1274     uint32_t unique_sc_add_count = 0;
1275     collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1276     for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1277     {
1278         if (AppendIfUnique (*pos, merge_symbol_into_function))
1279             ++unique_sc_add_count;
1280     }
1281     return unique_sc_add_count;
1282 }
1283 
1284 bool
1285 SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
1286 {
1287     collection::iterator pos, end = m_symbol_contexts.end();
1288     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1289     {
1290         if (*pos == sc)
1291             return false;
1292     }
1293     if (merge_symbol_into_function
1294         && sc.symbol    != nullptr
1295         && sc.comp_unit == nullptr
1296         && sc.function  == nullptr
1297         && sc.block     == nullptr
1298         && sc.line_entry.IsValid() == false)
1299     {
1300         if (sc.symbol->ValueIsAddress())
1301         {
1302             for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1303             {
1304                 // Don't merge symbols into inlined function symbol contexts
1305                 if (pos->block && pos->block->GetContainingInlinedBlock())
1306                     continue;
1307 
1308                 if (pos->function)
1309                 {
1310                     if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddressRef())
1311                     {
1312                         // Do we already have a function with this symbol?
1313                         if (pos->symbol == sc.symbol)
1314                             return false;
1315                         if (pos->symbol == nullptr)
1316                         {
1317                             pos->symbol = sc.symbol;
1318                             return false;
1319                         }
1320                     }
1321                 }
1322             }
1323         }
1324     }
1325     m_symbol_contexts.push_back(sc);
1326     return true;
1327 }
1328 
1329 bool
1330 SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
1331                                                           uint32_t start_idx,
1332                                                           uint32_t stop_idx)
1333 {
1334     if (symbol_sc.symbol    != nullptr
1335         && symbol_sc.comp_unit == nullptr
1336         && symbol_sc.function  == nullptr
1337         && symbol_sc.block     == nullptr
1338         && symbol_sc.line_entry.IsValid() == false)
1339     {
1340         if (symbol_sc.symbol->ValueIsAddress())
1341         {
1342             const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
1343             for (size_t i=start_idx; i<end; ++i)
1344             {
1345                 const SymbolContext &function_sc = m_symbol_contexts[i];
1346                 // Don't merge symbols into inlined function symbol contexts
1347                 if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
1348                     continue;
1349 
1350                 if (function_sc.function)
1351                 {
1352                     if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef())
1353                     {
1354                         // Do we already have a function with this symbol?
1355                         if (function_sc.symbol == symbol_sc.symbol)
1356                             return true; // Already have a symbol context with this symbol, return true
1357 
1358                         if (function_sc.symbol == nullptr)
1359                         {
1360                             // We successfully merged this symbol into an existing symbol context
1361                             m_symbol_contexts[i].symbol = symbol_sc.symbol;
1362                             return true;
1363                         }
1364                     }
1365                 }
1366             }
1367         }
1368     }
1369     return false;
1370 }
1371 
1372 void
1373 SymbolContextList::Clear()
1374 {
1375     m_symbol_contexts.clear();
1376 }
1377 
1378 void
1379 SymbolContextList::Dump(Stream *s, Target *target) const
1380 {
1381 
1382     *s << this << ": ";
1383     s->Indent();
1384     s->PutCString("SymbolContextList");
1385     s->EOL();
1386     s->IndentMore();
1387 
1388     collection::const_iterator pos, end = m_symbol_contexts.end();
1389     for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1390     {
1391         //pos->Dump(s, target);
1392         pos->GetDescription(s, eDescriptionLevelVerbose, target);
1393     }
1394     s->IndentLess();
1395 }
1396 
1397 bool
1398 SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
1399 {
1400     if (idx < m_symbol_contexts.size())
1401     {
1402         sc = m_symbol_contexts[idx];
1403         return true;
1404     }
1405     return false;
1406 }
1407 
1408 bool
1409 SymbolContextList::GetLastContext(SymbolContext& sc) const
1410 {
1411     if (!m_symbol_contexts.empty())
1412     {
1413         sc = m_symbol_contexts.back();
1414         return true;
1415     }
1416     return false;
1417 }
1418 
1419 bool
1420 SymbolContextList::RemoveContextAtIndex (size_t idx)
1421 {
1422     if (idx < m_symbol_contexts.size())
1423     {
1424         m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1425         return true;
1426     }
1427     return false;
1428 }
1429 
1430 uint32_t
1431 SymbolContextList::GetSize() const
1432 {
1433     return m_symbol_contexts.size();
1434 }
1435 
1436 uint32_t
1437 SymbolContextList::NumLineEntriesWithLine (uint32_t line) const
1438 {
1439     uint32_t match_count = 0;
1440     const size_t size = m_symbol_contexts.size();
1441     for (size_t idx = 0; idx<size; ++idx)
1442     {
1443         if (m_symbol_contexts[idx].line_entry.line == line)
1444             ++match_count;
1445     }
1446     return match_count;
1447 }
1448 
1449 void
1450 SymbolContextList::GetDescription(Stream *s,
1451                                   lldb::DescriptionLevel level,
1452                                   Target *target) const
1453 {
1454     const size_t size = m_symbol_contexts.size();
1455     for (size_t idx = 0; idx<size; ++idx)
1456         m_symbol_contexts[idx].GetDescription (s, level, target);
1457 }
1458 
1459 bool
1460 lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
1461 {
1462     const uint32_t size = lhs.GetSize();
1463     if (size != rhs.GetSize())
1464         return false;
1465 
1466     SymbolContext lhs_sc;
1467     SymbolContext rhs_sc;
1468     for (uint32_t i=0; i<size; ++i)
1469     {
1470         lhs.GetContextAtIndex(i, lhs_sc);
1471         rhs.GetContextAtIndex(i, rhs_sc);
1472         if (lhs_sc != rhs_sc)
1473             return false;
1474     }
1475     return true;
1476 }
1477 
1478 bool
1479 lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1480 {
1481     return !(lhs == rhs);
1482 }
1483 
1484