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