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