]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
MFV r316917: 7968 multi-threaded spa_sync()
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Symbol / SymbolContext.cpp
1 //===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Symbol/SymbolContext.h"
11
12 #include "lldb/Core/Log.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Host/Host.h"
16 #include "lldb/Host/StringConvert.h"
17 #include "lldb/Symbol/Block.h"
18 #include "lldb/Symbol/ClangASTContext.h"
19 #include "lldb/Symbol/CompileUnit.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Symbol/SymbolFile.h"
23 #include "lldb/Symbol/SymbolVendor.h"
24 #include "lldb/Symbol/Variable.h"
25 #include "lldb/Target/Target.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29
30 SymbolContext::SymbolContext()
31     : target_sp(), 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                                                      Error &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 //----------------------------------------------------------------------
803 //
804 //  SymbolContextSpecifier
805 //
806 //----------------------------------------------------------------------
807
808 SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp)
809     : m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_ap(),
810       m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
811       m_address_range_ap(), m_type(eNothingSpecified) {}
812
813 SymbolContextSpecifier::~SymbolContextSpecifier() {}
814
815 bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no,
816                                                   SpecificationType type) {
817   bool return_value = true;
818   switch (type) {
819   case eNothingSpecified:
820     Clear();
821     break;
822   case eLineStartSpecified:
823     m_start_line = line_no;
824     m_type |= eLineStartSpecified;
825     break;
826   case eLineEndSpecified:
827     m_end_line = line_no;
828     m_type |= eLineEndSpecified;
829     break;
830   default:
831     return_value = false;
832     break;
833   }
834   return return_value;
835 }
836
837 bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
838                                               SpecificationType type) {
839   bool return_value = true;
840   switch (type) {
841   case eNothingSpecified:
842     Clear();
843     break;
844   case eModuleSpecified: {
845     // See if we can find the Module, if so stick it in the SymbolContext.
846     FileSpec module_file_spec(spec_string, false);
847     ModuleSpec module_spec(module_file_spec);
848     lldb::ModuleSP module_sp(
849         m_target_sp->GetImages().FindFirstModule(module_spec));
850     m_type |= eModuleSpecified;
851     if (module_sp)
852       m_module_sp = module_sp;
853     else
854       m_module_spec.assign(spec_string);
855   } break;
856   case eFileSpecified:
857     // CompUnits can't necessarily be resolved here, since an inlined function
858     // might show up in
859     // a number of CompUnits.  Instead we just convert to a FileSpec and store
860     // it away.
861     m_file_spec_ap.reset(new FileSpec(spec_string, false));
862     m_type |= eFileSpecified;
863     break;
864   case eLineStartSpecified:
865     m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
866     if (return_value)
867       m_type |= eLineStartSpecified;
868     break;
869   case eLineEndSpecified:
870     m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value);
871     if (return_value)
872       m_type |= eLineEndSpecified;
873     break;
874   case eFunctionSpecified:
875     m_function_spec.assign(spec_string);
876     m_type |= eFunctionSpecified;
877     break;
878   case eClassOrNamespaceSpecified:
879     Clear();
880     m_class_name.assign(spec_string);
881     m_type = eClassOrNamespaceSpecified;
882     break;
883   case eAddressRangeSpecified:
884     // Not specified yet...
885     break;
886   }
887
888   return return_value;
889 }
890
891 void SymbolContextSpecifier::Clear() {
892   m_module_spec.clear();
893   m_file_spec_ap.reset();
894   m_function_spec.clear();
895   m_class_name.clear();
896   m_start_line = 0;
897   m_end_line = 0;
898   m_address_range_ap.reset();
899
900   m_type = eNothingSpecified;
901 }
902
903 bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
904   if (m_type == eNothingSpecified)
905     return true;
906
907   if (m_target_sp.get() != sc.target_sp.get())
908     return false;
909
910   if (m_type & eModuleSpecified) {
911     if (sc.module_sp) {
912       if (m_module_sp.get() != nullptr) {
913         if (m_module_sp.get() != sc.module_sp.get())
914           return false;
915       } else {
916         FileSpec module_file_spec(m_module_spec, false);
917         if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(),
918                              false))
919           return false;
920       }
921     }
922   }
923   if (m_type & eFileSpecified) {
924     if (m_file_spec_ap.get()) {
925       // If we don't have a block or a comp_unit, then we aren't going to match
926       // a source file.
927       if (sc.block == nullptr && sc.comp_unit == nullptr)
928         return false;
929
930       // Check if the block is present, and if so is it inlined:
931       bool was_inlined = false;
932       if (sc.block != nullptr) {
933         const InlineFunctionInfo *inline_info =
934             sc.block->GetInlinedFunctionInfo();
935         if (inline_info != nullptr) {
936           was_inlined = true;
937           if (!FileSpec::Equal(inline_info->GetDeclaration().GetFile(),
938                                *(m_file_spec_ap.get()), false))
939             return false;
940         }
941       }
942
943       // Next check the comp unit, but only if the SymbolContext was not
944       // inlined.
945       if (!was_inlined && sc.comp_unit != nullptr) {
946         if (!FileSpec::Equal(*(sc.comp_unit), *(m_file_spec_ap.get()), false))
947           return false;
948       }
949     }
950   }
951   if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) {
952     if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
953       return false;
954   }
955
956   if (m_type & eFunctionSpecified) {
957     // First check the current block, and if it is inlined, get the inlined
958     // function name:
959     bool was_inlined = false;
960     ConstString func_name(m_function_spec.c_str());
961
962     if (sc.block != nullptr) {
963       const InlineFunctionInfo *inline_info =
964           sc.block->GetInlinedFunctionInfo();
965       if (inline_info != nullptr) {
966         was_inlined = true;
967         const Mangled &name = inline_info->GetMangled();
968         if (!name.NameMatches(func_name, sc.function->GetLanguage()))
969           return false;
970       }
971     }
972     //  If it wasn't inlined, check the name in the function or symbol:
973     if (!was_inlined) {
974       if (sc.function != nullptr) {
975         if (!sc.function->GetMangled().NameMatches(func_name,
976                                                    sc.function->GetLanguage()))
977           return false;
978       } else if (sc.symbol != nullptr) {
979         if (!sc.symbol->GetMangled().NameMatches(func_name,
980                                                  sc.symbol->GetLanguage()))
981           return false;
982       }
983     }
984   }
985
986   return true;
987 }
988
989 bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) {
990   if (m_type & eAddressRangeSpecified) {
991
992   } else {
993     Address match_address(addr, nullptr);
994     SymbolContext sc;
995     m_target_sp->GetImages().ResolveSymbolContextForAddress(
996         match_address, eSymbolContextEverything, sc);
997     return SymbolContextMatches(sc);
998   }
999   return true;
1000 }
1001
1002 void SymbolContextSpecifier::GetDescription(
1003     Stream *s, lldb::DescriptionLevel level) const {
1004   char path_str[PATH_MAX + 1];
1005
1006   if (m_type == eNothingSpecified) {
1007     s->Printf("Nothing specified.\n");
1008   }
1009
1010   if (m_type == eModuleSpecified) {
1011     s->Indent();
1012     if (m_module_sp) {
1013       m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX);
1014       s->Printf("Module: %s\n", path_str);
1015     } else
1016       s->Printf("Module: %s\n", m_module_spec.c_str());
1017   }
1018
1019   if (m_type == eFileSpecified && m_file_spec_ap.get() != nullptr) {
1020     m_file_spec_ap->GetPath(path_str, PATH_MAX);
1021     s->Indent();
1022     s->Printf("File: %s", path_str);
1023     if (m_type == eLineStartSpecified) {
1024       s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line);
1025       if (m_type == eLineEndSpecified)
1026         s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
1027       else
1028         s->Printf("to end");
1029     } else if (m_type == eLineEndSpecified) {
1030       s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line);
1031     }
1032     s->Printf(".\n");
1033   }
1034
1035   if (m_type == eLineStartSpecified) {
1036     s->Indent();
1037     s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line);
1038     if (m_type == eLineEndSpecified)
1039       s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
1040     else
1041       s->Printf("to end");
1042     s->Printf(".\n");
1043   } else if (m_type == eLineEndSpecified) {
1044     s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
1045   }
1046
1047   if (m_type == eFunctionSpecified) {
1048     s->Indent();
1049     s->Printf("Function: %s.\n", m_function_spec.c_str());
1050   }
1051
1052   if (m_type == eClassOrNamespaceSpecified) {
1053     s->Indent();
1054     s->Printf("Class name: %s.\n", m_class_name.c_str());
1055   }
1056
1057   if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr) {
1058     s->Indent();
1059     s->PutCString("Address range: ");
1060     m_address_range_ap->Dump(s, m_target_sp.get(),
1061                              Address::DumpStyleLoadAddress,
1062                              Address::DumpStyleFileAddress);
1063     s->PutCString("\n");
1064   }
1065 }
1066
1067 //----------------------------------------------------------------------
1068 //
1069 //  SymbolContextList
1070 //
1071 //----------------------------------------------------------------------
1072
1073 SymbolContextList::SymbolContextList() : m_symbol_contexts() {}
1074
1075 SymbolContextList::~SymbolContextList() {}
1076
1077 void SymbolContextList::Append(const SymbolContext &sc) {
1078   m_symbol_contexts.push_back(sc);
1079 }
1080
1081 void SymbolContextList::Append(const SymbolContextList &sc_list) {
1082   collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1083   for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1084     m_symbol_contexts.push_back(*pos);
1085 }
1086
1087 uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list,
1088                                            bool merge_symbol_into_function) {
1089   uint32_t unique_sc_add_count = 0;
1090   collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1091   for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) {
1092     if (AppendIfUnique(*pos, merge_symbol_into_function))
1093       ++unique_sc_add_count;
1094   }
1095   return unique_sc_add_count;
1096 }
1097
1098 bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,
1099                                        bool merge_symbol_into_function) {
1100   collection::iterator pos, end = m_symbol_contexts.end();
1101   for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1102     if (*pos == sc)
1103       return false;
1104   }
1105   if (merge_symbol_into_function && sc.symbol != nullptr &&
1106       sc.comp_unit == nullptr && sc.function == nullptr &&
1107       sc.block == nullptr && sc.line_entry.IsValid() == false) {
1108     if (sc.symbol->ValueIsAddress()) {
1109       for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1110         // Don't merge symbols into inlined function symbol contexts
1111         if (pos->block && pos->block->GetContainingInlinedBlock())
1112           continue;
1113
1114         if (pos->function) {
1115           if (pos->function->GetAddressRange().GetBaseAddress() ==
1116               sc.symbol->GetAddressRef()) {
1117             // Do we already have a function with this symbol?
1118             if (pos->symbol == sc.symbol)
1119               return false;
1120             if (pos->symbol == nullptr) {
1121               pos->symbol = sc.symbol;
1122               return false;
1123             }
1124           }
1125         }
1126       }
1127     }
1128   }
1129   m_symbol_contexts.push_back(sc);
1130   return true;
1131 }
1132
1133 bool SymbolContextList::MergeSymbolContextIntoFunctionContext(
1134     const SymbolContext &symbol_sc, uint32_t start_idx, uint32_t stop_idx) {
1135   if (symbol_sc.symbol != nullptr && symbol_sc.comp_unit == nullptr &&
1136       symbol_sc.function == nullptr && symbol_sc.block == nullptr &&
1137       symbol_sc.line_entry.IsValid() == false) {
1138     if (symbol_sc.symbol->ValueIsAddress()) {
1139       const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
1140       for (size_t i = start_idx; i < end; ++i) {
1141         const SymbolContext &function_sc = m_symbol_contexts[i];
1142         // Don't merge symbols into inlined function symbol contexts
1143         if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
1144           continue;
1145
1146         if (function_sc.function) {
1147           if (function_sc.function->GetAddressRange().GetBaseAddress() ==
1148               symbol_sc.symbol->GetAddressRef()) {
1149             // Do we already have a function with this symbol?
1150             if (function_sc.symbol == symbol_sc.symbol)
1151               return true; // Already have a symbol context with this symbol,
1152                            // return true
1153
1154             if (function_sc.symbol == nullptr) {
1155               // We successfully merged this symbol into an existing symbol
1156               // context
1157               m_symbol_contexts[i].symbol = symbol_sc.symbol;
1158               return true;
1159             }
1160           }
1161         }
1162       }
1163     }
1164   }
1165   return false;
1166 }
1167
1168 void SymbolContextList::Clear() { m_symbol_contexts.clear(); }
1169
1170 void SymbolContextList::Dump(Stream *s, Target *target) const {
1171
1172   *s << this << ": ";
1173   s->Indent();
1174   s->PutCString("SymbolContextList");
1175   s->EOL();
1176   s->IndentMore();
1177
1178   collection::const_iterator pos, end = m_symbol_contexts.end();
1179   for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1180     // pos->Dump(s, target);
1181     pos->GetDescription(s, eDescriptionLevelVerbose, target);
1182   }
1183   s->IndentLess();
1184 }
1185
1186 bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const {
1187   if (idx < m_symbol_contexts.size()) {
1188     sc = m_symbol_contexts[idx];
1189     return true;
1190   }
1191   return false;
1192 }
1193
1194 bool SymbolContextList::GetLastContext(SymbolContext &sc) const {
1195   if (!m_symbol_contexts.empty()) {
1196     sc = m_symbol_contexts.back();
1197     return true;
1198   }
1199   return false;
1200 }
1201
1202 bool SymbolContextList::RemoveContextAtIndex(size_t idx) {
1203   if (idx < m_symbol_contexts.size()) {
1204     m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1205     return true;
1206   }
1207   return false;
1208 }
1209
1210 uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); }
1211
1212 uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const {
1213   uint32_t match_count = 0;
1214   const size_t size = m_symbol_contexts.size();
1215   for (size_t idx = 0; idx < size; ++idx) {
1216     if (m_symbol_contexts[idx].line_entry.line == line)
1217       ++match_count;
1218   }
1219   return match_count;
1220 }
1221
1222 void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level,
1223                                        Target *target) const {
1224   const size_t size = m_symbol_contexts.size();
1225   for (size_t idx = 0; idx < size; ++idx)
1226     m_symbol_contexts[idx].GetDescription(s, level, target);
1227 }
1228
1229 bool lldb_private::operator==(const SymbolContextList &lhs,
1230                               const SymbolContextList &rhs) {
1231   const uint32_t size = lhs.GetSize();
1232   if (size != rhs.GetSize())
1233     return false;
1234
1235   SymbolContext lhs_sc;
1236   SymbolContext rhs_sc;
1237   for (uint32_t i = 0; i < size; ++i) {
1238     lhs.GetContextAtIndex(i, lhs_sc);
1239     rhs.GetContextAtIndex(i, rhs_sc);
1240     if (lhs_sc != rhs_sc)
1241       return false;
1242   }
1243   return true;
1244 }
1245
1246 bool lldb_private::operator!=(const SymbolContextList &lhs,
1247                               const SymbolContextList &rhs) {
1248   return !(lhs == rhs);
1249 }