xref: /openbsd-src/gnu/llvm/lldb/source/Symbol/SymbolContext.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- SymbolContext.cpp -------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
10061da546Spatrick 
11*f6aab3d8Srobert #include "lldb/Core/Debugger.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/ModuleSpec.h"
14061da546Spatrick #include "lldb/Host/Host.h"
15061da546Spatrick #include "lldb/Symbol/Block.h"
16061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
17061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
18061da546Spatrick #include "lldb/Symbol/Symbol.h"
19061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
20061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
21061da546Spatrick #include "lldb/Symbol/Variable.h"
22061da546Spatrick #include "lldb/Target/Target.h"
23*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
24061da546Spatrick #include "lldb/Utility/Log.h"
25061da546Spatrick #include "lldb/Utility/StreamString.h"
26061da546Spatrick 
27061da546Spatrick using namespace lldb;
28061da546Spatrick using namespace lldb_private;
29061da546Spatrick 
SymbolContext()30be691f3bSpatrick SymbolContext::SymbolContext() : target_sp(), module_sp(), line_entry() {}
31061da546Spatrick 
SymbolContext(const ModuleSP & m,CompileUnit * cu,Function * f,Block * b,LineEntry * le,Symbol * s)32061da546Spatrick SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f,
33061da546Spatrick                              Block *b, LineEntry *le, Symbol *s)
34061da546Spatrick     : target_sp(), module_sp(m), comp_unit(cu), function(f), block(b),
35*f6aab3d8Srobert       line_entry(), symbol(s) {
36061da546Spatrick   if (le)
37061da546Spatrick     line_entry = *le;
38061da546Spatrick }
39061da546Spatrick 
SymbolContext(const TargetSP & t,const ModuleSP & m,CompileUnit * cu,Function * f,Block * b,LineEntry * le,Symbol * s)40061da546Spatrick SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP &m,
41061da546Spatrick                              CompileUnit *cu, Function *f, Block *b,
42061da546Spatrick                              LineEntry *le, Symbol *s)
43061da546Spatrick     : target_sp(t), module_sp(m), comp_unit(cu), function(f), block(b),
44*f6aab3d8Srobert       line_entry(), symbol(s) {
45061da546Spatrick   if (le)
46061da546Spatrick     line_entry = *le;
47061da546Spatrick }
48061da546Spatrick 
SymbolContext(SymbolContextScope * sc_scope)49061da546Spatrick SymbolContext::SymbolContext(SymbolContextScope *sc_scope)
50*f6aab3d8Srobert     : target_sp(), module_sp(), line_entry() {
51061da546Spatrick   sc_scope->CalculateSymbolContext(this);
52061da546Spatrick }
53061da546Spatrick 
54be691f3bSpatrick SymbolContext::~SymbolContext() = default;
55061da546Spatrick 
Clear(bool clear_target)56061da546Spatrick void SymbolContext::Clear(bool clear_target) {
57061da546Spatrick   if (clear_target)
58061da546Spatrick     target_sp.reset();
59061da546Spatrick   module_sp.reset();
60061da546Spatrick   comp_unit = nullptr;
61061da546Spatrick   function = nullptr;
62061da546Spatrick   block = nullptr;
63061da546Spatrick   line_entry.Clear();
64061da546Spatrick   symbol = nullptr;
65061da546Spatrick   variable = nullptr;
66061da546Spatrick }
67061da546Spatrick 
DumpStopContext(Stream * s,ExecutionContextScope * exe_scope,const Address & addr,bool show_fullpaths,bool show_module,bool show_inlined_frames,bool show_function_arguments,bool show_function_name) const68061da546Spatrick bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
69061da546Spatrick                                     const Address &addr, bool show_fullpaths,
70061da546Spatrick                                     bool show_module, bool show_inlined_frames,
71061da546Spatrick                                     bool show_function_arguments,
72061da546Spatrick                                     bool show_function_name) const {
73061da546Spatrick   bool dumped_something = false;
74061da546Spatrick   if (show_module && module_sp) {
75061da546Spatrick     if (show_fullpaths)
76061da546Spatrick       *s << module_sp->GetFileSpec();
77061da546Spatrick     else
78061da546Spatrick       *s << module_sp->GetFileSpec().GetFilename();
79061da546Spatrick     s->PutChar('`');
80061da546Spatrick     dumped_something = true;
81061da546Spatrick   }
82061da546Spatrick 
83061da546Spatrick   if (function != nullptr) {
84061da546Spatrick     SymbolContext inline_parent_sc;
85061da546Spatrick     Address inline_parent_addr;
86061da546Spatrick     if (!show_function_name) {
87061da546Spatrick       s->Printf("<");
88061da546Spatrick       dumped_something = true;
89061da546Spatrick     } else {
90061da546Spatrick       ConstString name;
91061da546Spatrick       if (!show_function_arguments)
92061da546Spatrick         name = function->GetNameNoArguments();
93061da546Spatrick       if (!name)
94061da546Spatrick         name = function->GetName();
95061da546Spatrick       if (name)
96061da546Spatrick         name.Dump(s);
97061da546Spatrick     }
98061da546Spatrick 
99061da546Spatrick     if (addr.IsValid()) {
100061da546Spatrick       const addr_t function_offset =
101061da546Spatrick           addr.GetOffset() -
102061da546Spatrick           function->GetAddressRange().GetBaseAddress().GetOffset();
103061da546Spatrick       if (!show_function_name) {
104061da546Spatrick         // Print +offset even if offset is 0
105061da546Spatrick         dumped_something = true;
106061da546Spatrick         s->Printf("+%" PRIu64 ">", function_offset);
107061da546Spatrick       } else if (function_offset) {
108061da546Spatrick         dumped_something = true;
109061da546Spatrick         s->Printf(" + %" PRIu64, function_offset);
110061da546Spatrick       }
111061da546Spatrick     }
112061da546Spatrick 
113061da546Spatrick     if (GetParentOfInlinedScope(addr, inline_parent_sc, inline_parent_addr)) {
114061da546Spatrick       dumped_something = true;
115061da546Spatrick       Block *inlined_block = block->GetContainingInlinedBlock();
116061da546Spatrick       const InlineFunctionInfo *inlined_block_info =
117061da546Spatrick           inlined_block->GetInlinedFunctionInfo();
118dda28197Spatrick       s->Printf(" [inlined] %s", inlined_block_info->GetName().GetCString());
119061da546Spatrick 
120061da546Spatrick       lldb_private::AddressRange block_range;
121061da546Spatrick       if (inlined_block->GetRangeContainingAddress(addr, block_range)) {
122061da546Spatrick         const addr_t inlined_function_offset =
123061da546Spatrick             addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
124061da546Spatrick         if (inlined_function_offset) {
125061da546Spatrick           s->Printf(" + %" PRIu64, inlined_function_offset);
126061da546Spatrick         }
127061da546Spatrick       }
128be691f3bSpatrick       // "line_entry" will always be valid as GetParentOfInlinedScope(...) will
129be691f3bSpatrick       // fill it in correctly with the calling file and line. Previous code
130be691f3bSpatrick       // was extracting the calling file and line from inlined_block_info and
131be691f3bSpatrick       // using it right away which is not correct. On the first call to this
132be691f3bSpatrick       // function "line_entry" will contain the actual line table entry. On
133be691f3bSpatrick       // susequent calls "line_entry" will contain the calling file and line
134be691f3bSpatrick       // from the previous inline info.
135be691f3bSpatrick       if (line_entry.IsValid()) {
136061da546Spatrick         s->PutCString(" at ");
137be691f3bSpatrick         line_entry.DumpStopContext(s, show_fullpaths);
138061da546Spatrick       }
139be691f3bSpatrick 
140061da546Spatrick       if (show_inlined_frames) {
141061da546Spatrick         s->EOL();
142061da546Spatrick         s->Indent();
143061da546Spatrick         const bool show_function_name = true;
144061da546Spatrick         return inline_parent_sc.DumpStopContext(
145061da546Spatrick             s, exe_scope, inline_parent_addr, show_fullpaths, show_module,
146061da546Spatrick             show_inlined_frames, show_function_arguments, show_function_name);
147061da546Spatrick       }
148061da546Spatrick     } else {
149061da546Spatrick       if (line_entry.IsValid()) {
150061da546Spatrick         dumped_something = true;
151061da546Spatrick         s->PutCString(" at ");
152061da546Spatrick         if (line_entry.DumpStopContext(s, show_fullpaths))
153061da546Spatrick           dumped_something = true;
154061da546Spatrick       }
155061da546Spatrick     }
156061da546Spatrick   } else if (symbol != nullptr) {
157061da546Spatrick     if (!show_function_name) {
158061da546Spatrick       s->Printf("<");
159061da546Spatrick       dumped_something = true;
160061da546Spatrick     } else if (symbol->GetName()) {
161061da546Spatrick       dumped_something = true;
162061da546Spatrick       if (symbol->GetType() == eSymbolTypeTrampoline)
163061da546Spatrick         s->PutCString("symbol stub for: ");
164061da546Spatrick       symbol->GetName().Dump(s);
165061da546Spatrick     }
166061da546Spatrick 
167061da546Spatrick     if (addr.IsValid() && symbol->ValueIsAddress()) {
168061da546Spatrick       const addr_t symbol_offset =
169061da546Spatrick           addr.GetOffset() - symbol->GetAddressRef().GetOffset();
170061da546Spatrick       if (!show_function_name) {
171061da546Spatrick         // Print +offset even if offset is 0
172061da546Spatrick         dumped_something = true;
173061da546Spatrick         s->Printf("+%" PRIu64 ">", symbol_offset);
174061da546Spatrick       } else if (symbol_offset) {
175061da546Spatrick         dumped_something = true;
176061da546Spatrick         s->Printf(" + %" PRIu64, symbol_offset);
177061da546Spatrick       }
178061da546Spatrick     }
179061da546Spatrick   } else if (addr.IsValid()) {
180061da546Spatrick     addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
181061da546Spatrick     dumped_something = true;
182061da546Spatrick   }
183061da546Spatrick   return dumped_something;
184061da546Spatrick }
185061da546Spatrick 
GetDescription(Stream * s,lldb::DescriptionLevel level,Target * target) const186061da546Spatrick void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
187061da546Spatrick                                    Target *target) const {
188061da546Spatrick   if (module_sp) {
189061da546Spatrick     s->Indent("     Module: file = \"");
190061da546Spatrick     module_sp->GetFileSpec().Dump(s->AsRawOstream());
191061da546Spatrick     *s << '"';
192061da546Spatrick     if (module_sp->GetArchitecture().IsValid())
193061da546Spatrick       s->Printf(", arch = \"%s\"",
194061da546Spatrick                 module_sp->GetArchitecture().GetArchitectureName());
195061da546Spatrick     s->EOL();
196061da546Spatrick   }
197061da546Spatrick 
198061da546Spatrick   if (comp_unit != nullptr) {
199061da546Spatrick     s->Indent("CompileUnit: ");
200061da546Spatrick     comp_unit->GetDescription(s, level);
201061da546Spatrick     s->EOL();
202061da546Spatrick   }
203061da546Spatrick 
204061da546Spatrick   if (function != nullptr) {
205061da546Spatrick     s->Indent("   Function: ");
206061da546Spatrick     function->GetDescription(s, level, target);
207061da546Spatrick     s->EOL();
208061da546Spatrick 
209061da546Spatrick     Type *func_type = function->GetType();
210061da546Spatrick     if (func_type) {
211061da546Spatrick       s->Indent("   FuncType: ");
212be691f3bSpatrick       func_type->GetDescription(s, level, false, target);
213061da546Spatrick       s->EOL();
214061da546Spatrick     }
215061da546Spatrick   }
216061da546Spatrick 
217061da546Spatrick   if (block != nullptr) {
218061da546Spatrick     std::vector<Block *> blocks;
219061da546Spatrick     blocks.push_back(block);
220061da546Spatrick     Block *parent_block = block->GetParent();
221061da546Spatrick 
222061da546Spatrick     while (parent_block) {
223061da546Spatrick       blocks.push_back(parent_block);
224061da546Spatrick       parent_block = parent_block->GetParent();
225061da546Spatrick     }
226061da546Spatrick     std::vector<Block *>::reverse_iterator pos;
227061da546Spatrick     std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
228061da546Spatrick     std::vector<Block *>::reverse_iterator end = blocks.rend();
229061da546Spatrick     for (pos = begin; pos != end; ++pos) {
230061da546Spatrick       if (pos == begin)
231061da546Spatrick         s->Indent("     Blocks: ");
232061da546Spatrick       else
233061da546Spatrick         s->Indent("             ");
234061da546Spatrick       (*pos)->GetDescription(s, function, level, target);
235061da546Spatrick       s->EOL();
236061da546Spatrick     }
237061da546Spatrick   }
238061da546Spatrick 
239061da546Spatrick   if (line_entry.IsValid()) {
240061da546Spatrick     s->Indent("  LineEntry: ");
241061da546Spatrick     line_entry.GetDescription(s, level, comp_unit, target, false);
242061da546Spatrick     s->EOL();
243061da546Spatrick   }
244061da546Spatrick 
245061da546Spatrick   if (symbol != nullptr) {
246061da546Spatrick     s->Indent("     Symbol: ");
247061da546Spatrick     symbol->GetDescription(s, level, target);
248061da546Spatrick     s->EOL();
249061da546Spatrick   }
250061da546Spatrick 
251061da546Spatrick   if (variable != nullptr) {
252061da546Spatrick     s->Indent("   Variable: ");
253061da546Spatrick 
254061da546Spatrick     s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID());
255061da546Spatrick 
256061da546Spatrick     switch (variable->GetScope()) {
257061da546Spatrick     case eValueTypeVariableGlobal:
258061da546Spatrick       s->PutCString("kind = global, ");
259061da546Spatrick       break;
260061da546Spatrick 
261061da546Spatrick     case eValueTypeVariableStatic:
262061da546Spatrick       s->PutCString("kind = static, ");
263061da546Spatrick       break;
264061da546Spatrick 
265061da546Spatrick     case eValueTypeVariableArgument:
266061da546Spatrick       s->PutCString("kind = argument, ");
267061da546Spatrick       break;
268061da546Spatrick 
269061da546Spatrick     case eValueTypeVariableLocal:
270061da546Spatrick       s->PutCString("kind = local, ");
271061da546Spatrick       break;
272061da546Spatrick 
273061da546Spatrick     case eValueTypeVariableThreadLocal:
274061da546Spatrick       s->PutCString("kind = thread local, ");
275061da546Spatrick       break;
276061da546Spatrick 
277061da546Spatrick     default:
278061da546Spatrick       break;
279061da546Spatrick     }
280061da546Spatrick 
281061da546Spatrick     s->Printf("name = \"%s\"\n", variable->GetName().GetCString());
282061da546Spatrick   }
283061da546Spatrick }
284061da546Spatrick 
GetResolvedMask() const285061da546Spatrick uint32_t SymbolContext::GetResolvedMask() const {
286061da546Spatrick   uint32_t resolved_mask = 0;
287061da546Spatrick   if (target_sp)
288061da546Spatrick     resolved_mask |= eSymbolContextTarget;
289061da546Spatrick   if (module_sp)
290061da546Spatrick     resolved_mask |= eSymbolContextModule;
291061da546Spatrick   if (comp_unit)
292061da546Spatrick     resolved_mask |= eSymbolContextCompUnit;
293061da546Spatrick   if (function)
294061da546Spatrick     resolved_mask |= eSymbolContextFunction;
295061da546Spatrick   if (block)
296061da546Spatrick     resolved_mask |= eSymbolContextBlock;
297061da546Spatrick   if (line_entry.IsValid())
298061da546Spatrick     resolved_mask |= eSymbolContextLineEntry;
299061da546Spatrick   if (symbol)
300061da546Spatrick     resolved_mask |= eSymbolContextSymbol;
301061da546Spatrick   if (variable)
302061da546Spatrick     resolved_mask |= eSymbolContextVariable;
303061da546Spatrick   return resolved_mask;
304061da546Spatrick }
305061da546Spatrick 
Dump(Stream * s,Target * target) const306061da546Spatrick void SymbolContext::Dump(Stream *s, Target *target) const {
307061da546Spatrick   *s << this << ": ";
308061da546Spatrick   s->Indent();
309061da546Spatrick   s->PutCString("SymbolContext");
310061da546Spatrick   s->IndentMore();
311061da546Spatrick   s->EOL();
312061da546Spatrick   s->IndentMore();
313061da546Spatrick   s->Indent();
314061da546Spatrick   *s << "Module       = " << module_sp.get() << ' ';
315061da546Spatrick   if (module_sp)
316061da546Spatrick     module_sp->GetFileSpec().Dump(s->AsRawOstream());
317061da546Spatrick   s->EOL();
318061da546Spatrick   s->Indent();
319061da546Spatrick   *s << "CompileUnit  = " << comp_unit;
320061da546Spatrick   if (comp_unit != nullptr)
321061da546Spatrick     s->Format(" {{{0:x-16}} {1}", comp_unit->GetID(),
322061da546Spatrick               comp_unit->GetPrimaryFile());
323061da546Spatrick   s->EOL();
324061da546Spatrick   s->Indent();
325061da546Spatrick   *s << "Function     = " << function;
326061da546Spatrick   if (function != nullptr) {
327061da546Spatrick     s->Format(" {{{0:x-16}} {1}, address-range = ", function->GetID(),
328061da546Spatrick               function->GetType()->GetName());
329061da546Spatrick     function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress,
330061da546Spatrick                                      Address::DumpStyleModuleWithFileAddress);
331061da546Spatrick     s->EOL();
332061da546Spatrick     s->Indent();
333061da546Spatrick     Type *func_type = function->GetType();
334061da546Spatrick     if (func_type) {
335061da546Spatrick       *s << "        Type = ";
336061da546Spatrick       func_type->Dump(s, false);
337061da546Spatrick     }
338061da546Spatrick   }
339061da546Spatrick   s->EOL();
340061da546Spatrick   s->Indent();
341061da546Spatrick   *s << "Block        = " << block;
342061da546Spatrick   if (block != nullptr)
343061da546Spatrick     s->Format(" {{{0:x-16}}", block->GetID());
344061da546Spatrick   s->EOL();
345061da546Spatrick   s->Indent();
346061da546Spatrick   *s << "LineEntry    = ";
347061da546Spatrick   line_entry.Dump(s, target, true, Address::DumpStyleLoadAddress,
348061da546Spatrick                   Address::DumpStyleModuleWithFileAddress, true);
349061da546Spatrick   s->EOL();
350061da546Spatrick   s->Indent();
351061da546Spatrick   *s << "Symbol       = " << symbol;
352061da546Spatrick   if (symbol != nullptr && symbol->GetMangled())
353061da546Spatrick     *s << ' ' << symbol->GetName().AsCString();
354061da546Spatrick   s->EOL();
355061da546Spatrick   *s << "Variable     = " << variable;
356061da546Spatrick   if (variable != nullptr) {
357061da546Spatrick     s->Format(" {{{0:x-16}} {1}", variable->GetID(),
358061da546Spatrick               variable->GetType()->GetName());
359061da546Spatrick     s->EOL();
360061da546Spatrick   }
361061da546Spatrick   s->IndentLess();
362061da546Spatrick   s->IndentLess();
363061da546Spatrick }
364061da546Spatrick 
operator ==(const SymbolContext & lhs,const SymbolContext & rhs)365061da546Spatrick bool lldb_private::operator==(const SymbolContext &lhs,
366061da546Spatrick                               const SymbolContext &rhs) {
367061da546Spatrick   return lhs.function == rhs.function && lhs.symbol == rhs.symbol &&
368061da546Spatrick          lhs.module_sp.get() == rhs.module_sp.get() &&
369061da546Spatrick          lhs.comp_unit == rhs.comp_unit &&
370061da546Spatrick          lhs.target_sp.get() == rhs.target_sp.get() &&
371061da546Spatrick          LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 &&
372061da546Spatrick          lhs.variable == rhs.variable;
373061da546Spatrick }
374061da546Spatrick 
operator !=(const SymbolContext & lhs,const SymbolContext & rhs)375061da546Spatrick bool lldb_private::operator!=(const SymbolContext &lhs,
376061da546Spatrick                               const SymbolContext &rhs) {
377061da546Spatrick   return !(lhs == rhs);
378061da546Spatrick }
379061da546Spatrick 
GetAddressRange(uint32_t scope,uint32_t range_idx,bool use_inline_block_range,AddressRange & range) const380061da546Spatrick bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx,
381061da546Spatrick                                     bool use_inline_block_range,
382061da546Spatrick                                     AddressRange &range) const {
383061da546Spatrick   if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) {
384061da546Spatrick     range = line_entry.range;
385061da546Spatrick     return true;
386061da546Spatrick   }
387061da546Spatrick 
388061da546Spatrick   if ((scope & eSymbolContextBlock) && (block != nullptr)) {
389061da546Spatrick     if (use_inline_block_range) {
390061da546Spatrick       Block *inline_block = block->GetContainingInlinedBlock();
391061da546Spatrick       if (inline_block)
392061da546Spatrick         return inline_block->GetRangeAtIndex(range_idx, range);
393061da546Spatrick     } else {
394061da546Spatrick       return block->GetRangeAtIndex(range_idx, range);
395061da546Spatrick     }
396061da546Spatrick   }
397061da546Spatrick 
398061da546Spatrick   if ((scope & eSymbolContextFunction) && (function != nullptr)) {
399061da546Spatrick     if (range_idx == 0) {
400061da546Spatrick       range = function->GetAddressRange();
401061da546Spatrick       return true;
402061da546Spatrick     }
403061da546Spatrick   }
404061da546Spatrick 
405061da546Spatrick   if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) {
406061da546Spatrick     if (range_idx == 0) {
407061da546Spatrick       if (symbol->ValueIsAddress()) {
408061da546Spatrick         range.GetBaseAddress() = symbol->GetAddressRef();
409061da546Spatrick         range.SetByteSize(symbol->GetByteSize());
410061da546Spatrick         return true;
411061da546Spatrick       }
412061da546Spatrick     }
413061da546Spatrick   }
414061da546Spatrick   range.Clear();
415061da546Spatrick   return false;
416061da546Spatrick }
417061da546Spatrick 
GetLanguage() const418061da546Spatrick LanguageType SymbolContext::GetLanguage() const {
419061da546Spatrick   LanguageType lang;
420061da546Spatrick   if (function && (lang = function->GetLanguage()) != eLanguageTypeUnknown) {
421061da546Spatrick     return lang;
422061da546Spatrick   } else if (variable &&
423061da546Spatrick              (lang = variable->GetLanguage()) != eLanguageTypeUnknown) {
424061da546Spatrick     return lang;
425061da546Spatrick   } else if (symbol && (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) {
426061da546Spatrick     return lang;
427061da546Spatrick   } else if (comp_unit &&
428061da546Spatrick              (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) {
429061da546Spatrick     return lang;
430061da546Spatrick   } else if (symbol) {
431061da546Spatrick     // If all else fails, try to guess the language from the name.
432061da546Spatrick     return symbol->GetMangled().GuessLanguage();
433061da546Spatrick   }
434061da546Spatrick   return eLanguageTypeUnknown;
435061da546Spatrick }
436061da546Spatrick 
GetParentOfInlinedScope(const Address & curr_frame_pc,SymbolContext & next_frame_sc,Address & next_frame_pc) const437061da546Spatrick bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc,
438061da546Spatrick                                             SymbolContext &next_frame_sc,
439061da546Spatrick                                             Address &next_frame_pc) const {
440061da546Spatrick   next_frame_sc.Clear(false);
441061da546Spatrick   next_frame_pc.Clear();
442061da546Spatrick 
443061da546Spatrick   if (block) {
444061da546Spatrick     // const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
445061da546Spatrick 
446061da546Spatrick     // In order to get the parent of an inlined function we first need to see
447061da546Spatrick     // if we are in an inlined block as "this->block" could be an inlined
448061da546Spatrick     // block, or a parent of "block" could be. So lets check if this block or
449061da546Spatrick     // one of this blocks parents is an inlined function.
450061da546Spatrick     Block *curr_inlined_block = block->GetContainingInlinedBlock();
451061da546Spatrick     if (curr_inlined_block) {
452061da546Spatrick       // "this->block" is contained in an inline function block, so to get the
453061da546Spatrick       // scope above the inlined block, we get the parent of the inlined block
454061da546Spatrick       // itself
455061da546Spatrick       Block *next_frame_block = curr_inlined_block->GetParent();
456061da546Spatrick       // Now calculate the symbol context of the containing block
457061da546Spatrick       next_frame_block->CalculateSymbolContext(&next_frame_sc);
458061da546Spatrick 
459061da546Spatrick       // If we get here we weren't able to find the return line entry using the
460061da546Spatrick       // nesting of the blocks and the line table.  So just use the call site
461061da546Spatrick       // info from our inlined block.
462061da546Spatrick 
463061da546Spatrick       AddressRange range;
464061da546Spatrick       if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) {
465061da546Spatrick         // To see there this new frame block it, we need to look at the call
466061da546Spatrick         // site information from
467061da546Spatrick         const InlineFunctionInfo *curr_inlined_block_inlined_info =
468061da546Spatrick             curr_inlined_block->GetInlinedFunctionInfo();
469061da546Spatrick         next_frame_pc = range.GetBaseAddress();
470061da546Spatrick         next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
471061da546Spatrick         next_frame_sc.line_entry.file =
472061da546Spatrick             curr_inlined_block_inlined_info->GetCallSite().GetFile();
473061da546Spatrick         next_frame_sc.line_entry.original_file =
474061da546Spatrick             curr_inlined_block_inlined_info->GetCallSite().GetFile();
475061da546Spatrick         next_frame_sc.line_entry.line =
476061da546Spatrick             curr_inlined_block_inlined_info->GetCallSite().GetLine();
477061da546Spatrick         next_frame_sc.line_entry.column =
478061da546Spatrick             curr_inlined_block_inlined_info->GetCallSite().GetColumn();
479061da546Spatrick         return true;
480061da546Spatrick       } else {
481*f6aab3d8Srobert         Log *log = GetLog(LLDBLog::Symbols);
482061da546Spatrick 
483061da546Spatrick         if (log) {
484061da546Spatrick           LLDB_LOGF(
485061da546Spatrick               log,
486061da546Spatrick               "warning: inlined block 0x%8.8" PRIx64
487061da546Spatrick               " doesn't have a range that contains file address 0x%" PRIx64,
488061da546Spatrick               curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
489061da546Spatrick         }
490061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
491061da546Spatrick         else {
492061da546Spatrick           ObjectFile *objfile = nullptr;
493061da546Spatrick           if (module_sp) {
494061da546Spatrick             if (SymbolFile *symbol_file = module_sp->GetSymbolFile())
495061da546Spatrick               objfile = symbol_file->GetObjectFile();
496061da546Spatrick           }
497061da546Spatrick           if (objfile) {
498*f6aab3d8Srobert             Debugger::ReportWarning(llvm::formatv(
499*f6aab3d8Srobert                 "inlined block {0:x} doesn't have a range that contains file "
500*f6aab3d8Srobert                 "address {1:x} in {2}",
501061da546Spatrick                 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(),
502*f6aab3d8Srobert                 objfile->GetFileSpec().GetPath()));
503061da546Spatrick           } else {
504*f6aab3d8Srobert             Debugger::ReportWarning(llvm::formatv(
505*f6aab3d8Srobert                 "inlined block {0:x} doesn't have a range that contains file "
506*f6aab3d8Srobert                 "address {1:x}",
507*f6aab3d8Srobert                 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()));
508061da546Spatrick           }
509061da546Spatrick         }
510061da546Spatrick #endif
511061da546Spatrick       }
512061da546Spatrick     }
513061da546Spatrick   }
514061da546Spatrick 
515061da546Spatrick   return false;
516061da546Spatrick }
517061da546Spatrick 
GetFunctionBlock()518061da546Spatrick Block *SymbolContext::GetFunctionBlock() {
519061da546Spatrick   if (function) {
520061da546Spatrick     if (block) {
521061da546Spatrick       // If this symbol context has a block, check to see if this block is
522061da546Spatrick       // itself, or is contained within a block with inlined function
523061da546Spatrick       // information. If so, then the inlined block is the block that defines
524061da546Spatrick       // the function.
525061da546Spatrick       Block *inlined_block = block->GetContainingInlinedBlock();
526061da546Spatrick       if (inlined_block)
527061da546Spatrick         return inlined_block;
528061da546Spatrick 
529061da546Spatrick       // The block in this symbol context is not inside an inlined block, so
530061da546Spatrick       // the block that defines the function is the function's top level block,
531061da546Spatrick       // which is returned below.
532061da546Spatrick     }
533061da546Spatrick 
534061da546Spatrick     // There is no block information in this symbol context, so we must assume
535061da546Spatrick     // that the block that is desired is the top level block of the function
536061da546Spatrick     // itself.
537061da546Spatrick     return &function->GetBlock(true);
538061da546Spatrick   }
539061da546Spatrick   return nullptr;
540061da546Spatrick }
541061da546Spatrick 
GetFunctionMethodInfo(lldb::LanguageType & language,bool & is_instance_method,ConstString & language_object_name)542061da546Spatrick bool SymbolContext::GetFunctionMethodInfo(lldb::LanguageType &language,
543061da546Spatrick                                           bool &is_instance_method,
544061da546Spatrick                                           ConstString &language_object_name)
545061da546Spatrick 
546061da546Spatrick {
547061da546Spatrick   Block *function_block = GetFunctionBlock();
548061da546Spatrick   if (function_block) {
549061da546Spatrick     CompilerDeclContext decl_ctx = function_block->GetDeclContext();
550061da546Spatrick     if (decl_ctx)
551061da546Spatrick       return decl_ctx.IsClassMethod(&language, &is_instance_method,
552061da546Spatrick                                     &language_object_name);
553061da546Spatrick   }
554061da546Spatrick   return false;
555061da546Spatrick }
556061da546Spatrick 
SortTypeList(TypeMap & type_map,TypeList & type_list) const557061da546Spatrick void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const {
558061da546Spatrick   Block *curr_block = block;
559061da546Spatrick   bool isInlinedblock = false;
560061da546Spatrick   if (curr_block != nullptr &&
561061da546Spatrick       curr_block->GetContainingInlinedBlock() != nullptr)
562061da546Spatrick     isInlinedblock = true;
563061da546Spatrick 
564061da546Spatrick   // Find all types that match the current block if we have one and put them
565061da546Spatrick   // first in the list. Keep iterating up through all blocks.
566061da546Spatrick   while (curr_block != nullptr && !isInlinedblock) {
567061da546Spatrick     type_map.ForEach(
568061da546Spatrick         [curr_block, &type_list](const lldb::TypeSP &type_sp) -> bool {
569061da546Spatrick           SymbolContextScope *scs = type_sp->GetSymbolContextScope();
570061da546Spatrick           if (scs && curr_block == scs->CalculateSymbolContextBlock())
571061da546Spatrick             type_list.Insert(type_sp);
572061da546Spatrick           return true; // Keep iterating
573061da546Spatrick         });
574061da546Spatrick 
575061da546Spatrick     // Remove any entries that are now in "type_list" from "type_map" since we
576061da546Spatrick     // can't remove from type_map while iterating
577061da546Spatrick     type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool {
578061da546Spatrick       type_map.Remove(type_sp);
579061da546Spatrick       return true; // Keep iterating
580061da546Spatrick     });
581061da546Spatrick     curr_block = curr_block->GetParent();
582061da546Spatrick   }
583061da546Spatrick   // Find all types that match the current function, if we have onem, and put
584061da546Spatrick   // them next in the list.
585061da546Spatrick   if (function != nullptr && !type_map.Empty()) {
586061da546Spatrick     const size_t old_type_list_size = type_list.GetSize();
587061da546Spatrick     type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
588061da546Spatrick       SymbolContextScope *scs = type_sp->GetSymbolContextScope();
589061da546Spatrick       if (scs && function == scs->CalculateSymbolContextFunction())
590061da546Spatrick         type_list.Insert(type_sp);
591061da546Spatrick       return true; // Keep iterating
592061da546Spatrick     });
593061da546Spatrick 
594061da546Spatrick     // Remove any entries that are now in "type_list" from "type_map" since we
595061da546Spatrick     // can't remove from type_map while iterating
596061da546Spatrick     const size_t new_type_list_size = type_list.GetSize();
597061da546Spatrick     if (new_type_list_size > old_type_list_size) {
598061da546Spatrick       for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
599061da546Spatrick         type_map.Remove(type_list.GetTypeAtIndex(i));
600061da546Spatrick     }
601061da546Spatrick   }
602061da546Spatrick   // Find all types that match the current compile unit, if we have one, and
603061da546Spatrick   // put them next in the list.
604061da546Spatrick   if (comp_unit != nullptr && !type_map.Empty()) {
605061da546Spatrick     const size_t old_type_list_size = type_list.GetSize();
606061da546Spatrick 
607061da546Spatrick     type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
608061da546Spatrick       SymbolContextScope *scs = type_sp->GetSymbolContextScope();
609061da546Spatrick       if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())
610061da546Spatrick         type_list.Insert(type_sp);
611061da546Spatrick       return true; // Keep iterating
612061da546Spatrick     });
613061da546Spatrick 
614061da546Spatrick     // Remove any entries that are now in "type_list" from "type_map" since we
615061da546Spatrick     // can't remove from type_map while iterating
616061da546Spatrick     const size_t new_type_list_size = type_list.GetSize();
617061da546Spatrick     if (new_type_list_size > old_type_list_size) {
618061da546Spatrick       for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
619061da546Spatrick         type_map.Remove(type_list.GetTypeAtIndex(i));
620061da546Spatrick     }
621061da546Spatrick   }
622061da546Spatrick   // Find all types that match the current module, if we have one, and put them
623061da546Spatrick   // next in the list.
624061da546Spatrick   if (module_sp && !type_map.Empty()) {
625061da546Spatrick     const size_t old_type_list_size = type_list.GetSize();
626061da546Spatrick     type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool {
627061da546Spatrick       SymbolContextScope *scs = type_sp->GetSymbolContextScope();
628061da546Spatrick       if (scs && module_sp == scs->CalculateSymbolContextModule())
629061da546Spatrick         type_list.Insert(type_sp);
630061da546Spatrick       return true; // Keep iterating
631061da546Spatrick     });
632061da546Spatrick     // Remove any entries that are now in "type_list" from "type_map" since we
633061da546Spatrick     // can't remove from type_map while iterating
634061da546Spatrick     const size_t new_type_list_size = type_list.GetSize();
635061da546Spatrick     if (new_type_list_size > old_type_list_size) {
636061da546Spatrick       for (size_t i = old_type_list_size; i < new_type_list_size; ++i)
637061da546Spatrick         type_map.Remove(type_list.GetTypeAtIndex(i));
638061da546Spatrick     }
639061da546Spatrick   }
640061da546Spatrick   // Any types that are left get copied into the list an any order.
641061da546Spatrick   if (!type_map.Empty()) {
642061da546Spatrick     type_map.ForEach([&type_list](const lldb::TypeSP &type_sp) -> bool {
643061da546Spatrick       type_list.Insert(type_sp);
644061da546Spatrick       return true; // Keep iterating
645061da546Spatrick     });
646061da546Spatrick   }
647061da546Spatrick }
648061da546Spatrick 
649061da546Spatrick ConstString
GetFunctionName(Mangled::NamePreference preference) const650061da546Spatrick SymbolContext::GetFunctionName(Mangled::NamePreference preference) const {
651061da546Spatrick   if (function) {
652061da546Spatrick     if (block) {
653061da546Spatrick       Block *inlined_block = block->GetContainingInlinedBlock();
654061da546Spatrick 
655061da546Spatrick       if (inlined_block) {
656061da546Spatrick         const InlineFunctionInfo *inline_info =
657061da546Spatrick             inlined_block->GetInlinedFunctionInfo();
658061da546Spatrick         if (inline_info)
659dda28197Spatrick           return inline_info->GetName();
660061da546Spatrick       }
661061da546Spatrick     }
662dda28197Spatrick     return function->GetMangled().GetName(preference);
663061da546Spatrick   } else if (symbol && symbol->ValueIsAddress()) {
664dda28197Spatrick     return symbol->GetMangled().GetName(preference);
665061da546Spatrick   } else {
666061da546Spatrick     // No function, return an empty string.
667061da546Spatrick     return ConstString();
668061da546Spatrick   }
669061da546Spatrick }
670061da546Spatrick 
GetFunctionStartLineEntry() const671061da546Spatrick LineEntry SymbolContext::GetFunctionStartLineEntry() const {
672061da546Spatrick   LineEntry line_entry;
673061da546Spatrick   Address start_addr;
674061da546Spatrick   if (block) {
675061da546Spatrick     Block *inlined_block = block->GetContainingInlinedBlock();
676061da546Spatrick     if (inlined_block) {
677061da546Spatrick       if (inlined_block->GetStartAddress(start_addr)) {
678061da546Spatrick         if (start_addr.CalculateSymbolContextLineEntry(line_entry))
679061da546Spatrick           return line_entry;
680061da546Spatrick       }
681061da546Spatrick       return LineEntry();
682061da546Spatrick     }
683061da546Spatrick   }
684061da546Spatrick 
685061da546Spatrick   if (function) {
686061da546Spatrick     if (function->GetAddressRange()
687061da546Spatrick             .GetBaseAddress()
688061da546Spatrick             .CalculateSymbolContextLineEntry(line_entry))
689061da546Spatrick       return line_entry;
690061da546Spatrick   }
691061da546Spatrick   return LineEntry();
692061da546Spatrick }
693061da546Spatrick 
GetAddressRangeFromHereToEndLine(uint32_t end_line,AddressRange & range,Status & error)694061da546Spatrick bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line,
695061da546Spatrick                                                      AddressRange &range,
696061da546Spatrick                                                      Status &error) {
697061da546Spatrick   if (!line_entry.IsValid()) {
698061da546Spatrick     error.SetErrorString("Symbol context has no line table.");
699061da546Spatrick     return false;
700061da546Spatrick   }
701061da546Spatrick 
702061da546Spatrick   range = line_entry.range;
703061da546Spatrick   if (line_entry.line > end_line) {
704061da546Spatrick     error.SetErrorStringWithFormat(
705061da546Spatrick         "end line option %d must be after the current line: %d", end_line,
706061da546Spatrick         line_entry.line);
707061da546Spatrick     return false;
708061da546Spatrick   }
709061da546Spatrick 
710061da546Spatrick   uint32_t line_index = 0;
711061da546Spatrick   bool found = false;
712061da546Spatrick   while (true) {
713061da546Spatrick     LineEntry this_line;
714061da546Spatrick     line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr,
715061da546Spatrick                                           false, &this_line);
716061da546Spatrick     if (line_index == UINT32_MAX)
717061da546Spatrick       break;
718061da546Spatrick     if (LineEntry::Compare(this_line, line_entry) == 0) {
719061da546Spatrick       found = true;
720061da546Spatrick       break;
721061da546Spatrick     }
722061da546Spatrick   }
723061da546Spatrick 
724061da546Spatrick   LineEntry end_entry;
725061da546Spatrick   if (!found) {
726061da546Spatrick     // Can't find the index of the SymbolContext's line entry in the
727061da546Spatrick     // SymbolContext's CompUnit.
728061da546Spatrick     error.SetErrorString(
729061da546Spatrick         "Can't find the current line entry in the CompUnit - can't process "
730061da546Spatrick         "the end-line option");
731061da546Spatrick     return false;
732061da546Spatrick   }
733061da546Spatrick 
734061da546Spatrick   line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false,
735061da546Spatrick                                         &end_entry);
736061da546Spatrick   if (line_index == UINT32_MAX) {
737061da546Spatrick     error.SetErrorStringWithFormat(
738061da546Spatrick         "could not find a line table entry corresponding "
739061da546Spatrick         "to end line number %d",
740061da546Spatrick         end_line);
741061da546Spatrick     return false;
742061da546Spatrick   }
743061da546Spatrick 
744061da546Spatrick   Block *func_block = GetFunctionBlock();
745061da546Spatrick   if (func_block && func_block->GetRangeIndexContainingAddress(
746061da546Spatrick                         end_entry.range.GetBaseAddress()) == UINT32_MAX) {
747061da546Spatrick     error.SetErrorStringWithFormat(
748061da546Spatrick         "end line number %d is not contained within the current function.",
749061da546Spatrick         end_line);
750061da546Spatrick     return false;
751061da546Spatrick   }
752061da546Spatrick 
753061da546Spatrick   lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() -
754061da546Spatrick                             range.GetBaseAddress().GetFileAddress();
755061da546Spatrick   range.SetByteSize(range_size);
756061da546Spatrick   return true;
757061da546Spatrick }
758061da546Spatrick 
FindBestGlobalDataSymbol(ConstString name,Status & error)759061da546Spatrick const Symbol *SymbolContext::FindBestGlobalDataSymbol(ConstString name,
760061da546Spatrick                                                       Status &error) {
761061da546Spatrick   error.Clear();
762061da546Spatrick 
763061da546Spatrick   if (!target_sp) {
764061da546Spatrick     return nullptr;
765061da546Spatrick   }
766061da546Spatrick 
767061da546Spatrick   Target &target = *target_sp;
768061da546Spatrick   Module *module = module_sp.get();
769061da546Spatrick 
770061da546Spatrick   auto ProcessMatches = [this, &name, &target,
771061da546Spatrick                          module](SymbolContextList &sc_list,
772061da546Spatrick                                  Status &error) -> const Symbol * {
773061da546Spatrick     llvm::SmallVector<const Symbol *, 1> external_symbols;
774061da546Spatrick     llvm::SmallVector<const Symbol *, 1> internal_symbols;
775061da546Spatrick     const uint32_t matches = sc_list.GetSize();
776061da546Spatrick     for (uint32_t i = 0; i < matches; ++i) {
777061da546Spatrick       SymbolContext sym_ctx;
778061da546Spatrick       sc_list.GetContextAtIndex(i, sym_ctx);
779061da546Spatrick       if (sym_ctx.symbol) {
780061da546Spatrick         const Symbol *symbol = sym_ctx.symbol;
781061da546Spatrick         const Address sym_address = symbol->GetAddress();
782061da546Spatrick 
783061da546Spatrick         if (sym_address.IsValid()) {
784061da546Spatrick           switch (symbol->GetType()) {
785061da546Spatrick           case eSymbolTypeData:
786061da546Spatrick           case eSymbolTypeRuntime:
787061da546Spatrick           case eSymbolTypeAbsolute:
788061da546Spatrick           case eSymbolTypeObjCClass:
789061da546Spatrick           case eSymbolTypeObjCMetaClass:
790061da546Spatrick           case eSymbolTypeObjCIVar:
791061da546Spatrick             if (symbol->GetDemangledNameIsSynthesized()) {
792061da546Spatrick               // If the demangled name was synthesized, then don't use it for
793061da546Spatrick               // expressions. Only let the symbol match if the mangled named
794061da546Spatrick               // matches for these symbols.
795061da546Spatrick               if (symbol->GetMangled().GetMangledName() != name)
796061da546Spatrick                 break;
797061da546Spatrick             }
798061da546Spatrick             if (symbol->IsExternal()) {
799061da546Spatrick               external_symbols.push_back(symbol);
800061da546Spatrick             } else {
801061da546Spatrick               internal_symbols.push_back(symbol);
802061da546Spatrick             }
803061da546Spatrick             break;
804061da546Spatrick           case eSymbolTypeReExported: {
805061da546Spatrick             ConstString reexport_name = symbol->GetReExportedSymbolName();
806061da546Spatrick             if (reexport_name) {
807061da546Spatrick               ModuleSP reexport_module_sp;
808061da546Spatrick               ModuleSpec reexport_module_spec;
809061da546Spatrick               reexport_module_spec.GetPlatformFileSpec() =
810061da546Spatrick                   symbol->GetReExportedSymbolSharedLibrary();
811061da546Spatrick               if (reexport_module_spec.GetPlatformFileSpec()) {
812061da546Spatrick                 reexport_module_sp =
813061da546Spatrick                     target.GetImages().FindFirstModule(reexport_module_spec);
814061da546Spatrick                 if (!reexport_module_sp) {
815*f6aab3d8Srobert                   reexport_module_spec.GetPlatformFileSpec().ClearDirectory();
816061da546Spatrick                   reexport_module_sp =
817061da546Spatrick                       target.GetImages().FindFirstModule(reexport_module_spec);
818061da546Spatrick                 }
819061da546Spatrick               }
820061da546Spatrick               // Don't allow us to try and resolve a re-exported symbol if it
821061da546Spatrick               // is the same as the current symbol
822061da546Spatrick               if (name == symbol->GetReExportedSymbolName() &&
823061da546Spatrick                   module == reexport_module_sp.get())
824061da546Spatrick                 return nullptr;
825061da546Spatrick 
826061da546Spatrick               return FindBestGlobalDataSymbol(symbol->GetReExportedSymbolName(),
827061da546Spatrick                                               error);
828061da546Spatrick             }
829061da546Spatrick           } break;
830061da546Spatrick 
831061da546Spatrick           case eSymbolTypeCode: // We already lookup functions elsewhere
832061da546Spatrick           case eSymbolTypeVariable:
833061da546Spatrick           case eSymbolTypeLocal:
834061da546Spatrick           case eSymbolTypeParam:
835061da546Spatrick           case eSymbolTypeTrampoline:
836061da546Spatrick           case eSymbolTypeInvalid:
837061da546Spatrick           case eSymbolTypeException:
838061da546Spatrick           case eSymbolTypeSourceFile:
839061da546Spatrick           case eSymbolTypeHeaderFile:
840061da546Spatrick           case eSymbolTypeObjectFile:
841061da546Spatrick           case eSymbolTypeCommonBlock:
842061da546Spatrick           case eSymbolTypeBlock:
843061da546Spatrick           case eSymbolTypeVariableType:
844061da546Spatrick           case eSymbolTypeLineEntry:
845061da546Spatrick           case eSymbolTypeLineHeader:
846061da546Spatrick           case eSymbolTypeScopeBegin:
847061da546Spatrick           case eSymbolTypeScopeEnd:
848061da546Spatrick           case eSymbolTypeAdditional:
849061da546Spatrick           case eSymbolTypeCompiler:
850061da546Spatrick           case eSymbolTypeInstrumentation:
851061da546Spatrick           case eSymbolTypeUndefined:
852061da546Spatrick           case eSymbolTypeResolver:
853061da546Spatrick             break;
854061da546Spatrick           }
855061da546Spatrick         }
856061da546Spatrick       }
857061da546Spatrick     }
858061da546Spatrick 
859061da546Spatrick     if (external_symbols.size() > 1) {
860061da546Spatrick       StreamString ss;
861061da546Spatrick       ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());
862061da546Spatrick       for (const Symbol *symbol : external_symbols) {
863061da546Spatrick         symbol->GetDescription(&ss, eDescriptionLevelFull, &target);
864061da546Spatrick       }
865061da546Spatrick       ss.PutChar('\n');
866061da546Spatrick       error.SetErrorString(ss.GetData());
867061da546Spatrick       return nullptr;
868061da546Spatrick     } else if (external_symbols.size()) {
869061da546Spatrick       return external_symbols[0];
870061da546Spatrick     } else if (internal_symbols.size() > 1) {
871061da546Spatrick       StreamString ss;
872061da546Spatrick       ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString());
873061da546Spatrick       for (const Symbol *symbol : internal_symbols) {
874061da546Spatrick         symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target);
875061da546Spatrick         ss.PutChar('\n');
876061da546Spatrick       }
877061da546Spatrick       error.SetErrorString(ss.GetData());
878061da546Spatrick       return nullptr;
879061da546Spatrick     } else if (internal_symbols.size()) {
880061da546Spatrick       return internal_symbols[0];
881061da546Spatrick     } else {
882061da546Spatrick       return nullptr;
883061da546Spatrick     }
884061da546Spatrick   };
885061da546Spatrick 
886061da546Spatrick   if (module) {
887061da546Spatrick     SymbolContextList sc_list;
888061da546Spatrick     module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
889061da546Spatrick     const Symbol *const module_symbol = ProcessMatches(sc_list, error);
890061da546Spatrick 
891061da546Spatrick     if (!error.Success()) {
892061da546Spatrick       return nullptr;
893061da546Spatrick     } else if (module_symbol) {
894061da546Spatrick       return module_symbol;
895061da546Spatrick     }
896061da546Spatrick   }
897061da546Spatrick 
898061da546Spatrick   {
899061da546Spatrick     SymbolContextList sc_list;
900061da546Spatrick     target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
901061da546Spatrick                                                   sc_list);
902061da546Spatrick     const Symbol *const target_symbol = ProcessMatches(sc_list, error);
903061da546Spatrick 
904061da546Spatrick     if (!error.Success()) {
905061da546Spatrick       return nullptr;
906061da546Spatrick     } else if (target_symbol) {
907061da546Spatrick       return target_symbol;
908061da546Spatrick     }
909061da546Spatrick   }
910061da546Spatrick 
911061da546Spatrick   return nullptr; // no error; we just didn't find anything
912061da546Spatrick }
913061da546Spatrick 
914061da546Spatrick //
915061da546Spatrick //  SymbolContextSpecifier
916061da546Spatrick //
917061da546Spatrick 
SymbolContextSpecifier(const TargetSP & target_sp)918061da546Spatrick SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp)
919061da546Spatrick     : m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_up(),
920061da546Spatrick       m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
921061da546Spatrick       m_address_range_up(), m_type(eNothingSpecified) {}
922061da546Spatrick 
923be691f3bSpatrick SymbolContextSpecifier::~SymbolContextSpecifier() = default;
924061da546Spatrick 
AddLineSpecification(uint32_t line_no,SpecificationType type)925061da546Spatrick bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no,
926061da546Spatrick                                                   SpecificationType type) {
927061da546Spatrick   bool return_value = true;
928061da546Spatrick   switch (type) {
929061da546Spatrick   case eNothingSpecified:
930061da546Spatrick     Clear();
931061da546Spatrick     break;
932061da546Spatrick   case eLineStartSpecified:
933061da546Spatrick     m_start_line = line_no;
934061da546Spatrick     m_type |= eLineStartSpecified;
935061da546Spatrick     break;
936061da546Spatrick   case eLineEndSpecified:
937061da546Spatrick     m_end_line = line_no;
938061da546Spatrick     m_type |= eLineEndSpecified;
939061da546Spatrick     break;
940061da546Spatrick   default:
941061da546Spatrick     return_value = false;
942061da546Spatrick     break;
943061da546Spatrick   }
944061da546Spatrick   return return_value;
945061da546Spatrick }
946061da546Spatrick 
AddSpecification(const char * spec_string,SpecificationType type)947061da546Spatrick bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
948061da546Spatrick                                               SpecificationType type) {
949061da546Spatrick   bool return_value = true;
950061da546Spatrick   switch (type) {
951061da546Spatrick   case eNothingSpecified:
952061da546Spatrick     Clear();
953061da546Spatrick     break;
954061da546Spatrick   case eModuleSpecified: {
955061da546Spatrick     // See if we can find the Module, if so stick it in the SymbolContext.
956061da546Spatrick     FileSpec module_file_spec(spec_string);
957061da546Spatrick     ModuleSpec module_spec(module_file_spec);
958*f6aab3d8Srobert     lldb::ModuleSP module_sp =
959*f6aab3d8Srobert         m_target_sp ? m_target_sp->GetImages().FindFirstModule(module_spec)
960*f6aab3d8Srobert                     : nullptr;
961061da546Spatrick     m_type |= eModuleSpecified;
962061da546Spatrick     if (module_sp)
963061da546Spatrick       m_module_sp = module_sp;
964061da546Spatrick     else
965061da546Spatrick       m_module_spec.assign(spec_string);
966061da546Spatrick   } break;
967061da546Spatrick   case eFileSpecified:
968061da546Spatrick     // CompUnits can't necessarily be resolved here, since an inlined function
969061da546Spatrick     // might show up in a number of CompUnits.  Instead we just convert to a
970061da546Spatrick     // FileSpec and store it away.
971dda28197Spatrick     m_file_spec_up = std::make_unique<FileSpec>(spec_string);
972061da546Spatrick     m_type |= eFileSpecified;
973061da546Spatrick     break;
974061da546Spatrick   case eLineStartSpecified:
975*f6aab3d8Srobert     if ((return_value = llvm::to_integer(spec_string, m_start_line)))
976061da546Spatrick       m_type |= eLineStartSpecified;
977061da546Spatrick     break;
978061da546Spatrick   case eLineEndSpecified:
979*f6aab3d8Srobert     if ((return_value = llvm::to_integer(spec_string, m_end_line)))
980061da546Spatrick       m_type |= eLineEndSpecified;
981061da546Spatrick     break;
982061da546Spatrick   case eFunctionSpecified:
983061da546Spatrick     m_function_spec.assign(spec_string);
984061da546Spatrick     m_type |= eFunctionSpecified;
985061da546Spatrick     break;
986061da546Spatrick   case eClassOrNamespaceSpecified:
987061da546Spatrick     Clear();
988061da546Spatrick     m_class_name.assign(spec_string);
989061da546Spatrick     m_type = eClassOrNamespaceSpecified;
990061da546Spatrick     break;
991061da546Spatrick   case eAddressRangeSpecified:
992061da546Spatrick     // Not specified yet...
993061da546Spatrick     break;
994061da546Spatrick   }
995061da546Spatrick 
996061da546Spatrick   return return_value;
997061da546Spatrick }
998061da546Spatrick 
Clear()999061da546Spatrick void SymbolContextSpecifier::Clear() {
1000061da546Spatrick   m_module_spec.clear();
1001061da546Spatrick   m_file_spec_up.reset();
1002061da546Spatrick   m_function_spec.clear();
1003061da546Spatrick   m_class_name.clear();
1004061da546Spatrick   m_start_line = 0;
1005061da546Spatrick   m_end_line = 0;
1006061da546Spatrick   m_address_range_up.reset();
1007061da546Spatrick 
1008061da546Spatrick   m_type = eNothingSpecified;
1009061da546Spatrick }
1010061da546Spatrick 
SymbolContextMatches(const SymbolContext & sc)1011be691f3bSpatrick bool SymbolContextSpecifier::SymbolContextMatches(const SymbolContext &sc) {
1012061da546Spatrick   if (m_type == eNothingSpecified)
1013061da546Spatrick     return true;
1014061da546Spatrick 
1015be691f3bSpatrick   // Only compare targets if this specifier has one and it's not the Dummy
1016be691f3bSpatrick   // target.  Otherwise if a specifier gets made in the dummy target and
1017be691f3bSpatrick   // copied over we'll artificially fail the comparision.
1018be691f3bSpatrick   if (m_target_sp && !m_target_sp->IsDummyTarget() &&
1019be691f3bSpatrick       m_target_sp != sc.target_sp)
1020061da546Spatrick     return false;
1021061da546Spatrick 
1022061da546Spatrick   if (m_type & eModuleSpecified) {
1023061da546Spatrick     if (sc.module_sp) {
1024061da546Spatrick       if (m_module_sp.get() != nullptr) {
1025061da546Spatrick         if (m_module_sp.get() != sc.module_sp.get())
1026061da546Spatrick           return false;
1027061da546Spatrick       } else {
1028061da546Spatrick         FileSpec module_file_spec(m_module_spec);
1029061da546Spatrick         if (!FileSpec::Match(module_file_spec, sc.module_sp->GetFileSpec()))
1030061da546Spatrick           return false;
1031061da546Spatrick       }
1032061da546Spatrick     }
1033061da546Spatrick   }
1034061da546Spatrick   if (m_type & eFileSpecified) {
1035061da546Spatrick     if (m_file_spec_up) {
1036061da546Spatrick       // If we don't have a block or a comp_unit, then we aren't going to match
1037061da546Spatrick       // a source file.
1038061da546Spatrick       if (sc.block == nullptr && sc.comp_unit == nullptr)
1039061da546Spatrick         return false;
1040061da546Spatrick 
1041061da546Spatrick       // Check if the block is present, and if so is it inlined:
1042061da546Spatrick       bool was_inlined = false;
1043061da546Spatrick       if (sc.block != nullptr) {
1044061da546Spatrick         const InlineFunctionInfo *inline_info =
1045061da546Spatrick             sc.block->GetInlinedFunctionInfo();
1046061da546Spatrick         if (inline_info != nullptr) {
1047061da546Spatrick           was_inlined = true;
1048061da546Spatrick           if (!FileSpec::Match(*m_file_spec_up,
1049061da546Spatrick                                inline_info->GetDeclaration().GetFile()))
1050061da546Spatrick             return false;
1051061da546Spatrick         }
1052061da546Spatrick       }
1053061da546Spatrick 
1054061da546Spatrick       // Next check the comp unit, but only if the SymbolContext was not
1055061da546Spatrick       // inlined.
1056061da546Spatrick       if (!was_inlined && sc.comp_unit != nullptr) {
1057061da546Spatrick         if (!FileSpec::Match(*m_file_spec_up, sc.comp_unit->GetPrimaryFile()))
1058061da546Spatrick           return false;
1059061da546Spatrick       }
1060061da546Spatrick     }
1061061da546Spatrick   }
1062061da546Spatrick   if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) {
1063061da546Spatrick     if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
1064061da546Spatrick       return false;
1065061da546Spatrick   }
1066061da546Spatrick 
1067061da546Spatrick   if (m_type & eFunctionSpecified) {
1068061da546Spatrick     // First check the current block, and if it is inlined, get the inlined
1069061da546Spatrick     // function name:
1070061da546Spatrick     bool was_inlined = false;
1071061da546Spatrick     ConstString func_name(m_function_spec.c_str());
1072061da546Spatrick 
1073061da546Spatrick     if (sc.block != nullptr) {
1074061da546Spatrick       const InlineFunctionInfo *inline_info =
1075061da546Spatrick           sc.block->GetInlinedFunctionInfo();
1076061da546Spatrick       if (inline_info != nullptr) {
1077061da546Spatrick         was_inlined = true;
1078061da546Spatrick         const Mangled &name = inline_info->GetMangled();
1079dda28197Spatrick         if (!name.NameMatches(func_name))
1080061da546Spatrick           return false;
1081061da546Spatrick       }
1082061da546Spatrick     }
1083061da546Spatrick     //  If it wasn't inlined, check the name in the function or symbol:
1084061da546Spatrick     if (!was_inlined) {
1085061da546Spatrick       if (sc.function != nullptr) {
1086dda28197Spatrick         if (!sc.function->GetMangled().NameMatches(func_name))
1087061da546Spatrick           return false;
1088061da546Spatrick       } else if (sc.symbol != nullptr) {
1089dda28197Spatrick         if (!sc.symbol->GetMangled().NameMatches(func_name))
1090061da546Spatrick           return false;
1091061da546Spatrick       }
1092061da546Spatrick     }
1093061da546Spatrick   }
1094061da546Spatrick 
1095061da546Spatrick   return true;
1096061da546Spatrick }
1097061da546Spatrick 
AddressMatches(lldb::addr_t addr)1098061da546Spatrick bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) {
1099061da546Spatrick   if (m_type & eAddressRangeSpecified) {
1100061da546Spatrick 
1101061da546Spatrick   } else {
1102061da546Spatrick     Address match_address(addr, nullptr);
1103061da546Spatrick     SymbolContext sc;
1104061da546Spatrick     m_target_sp->GetImages().ResolveSymbolContextForAddress(
1105061da546Spatrick         match_address, eSymbolContextEverything, sc);
1106061da546Spatrick     return SymbolContextMatches(sc);
1107061da546Spatrick   }
1108061da546Spatrick   return true;
1109061da546Spatrick }
1110061da546Spatrick 
GetDescription(Stream * s,lldb::DescriptionLevel level) const1111061da546Spatrick void SymbolContextSpecifier::GetDescription(
1112061da546Spatrick     Stream *s, lldb::DescriptionLevel level) const {
1113061da546Spatrick   char path_str[PATH_MAX + 1];
1114061da546Spatrick 
1115061da546Spatrick   if (m_type == eNothingSpecified) {
1116061da546Spatrick     s->Printf("Nothing specified.\n");
1117061da546Spatrick   }
1118061da546Spatrick 
1119061da546Spatrick   if (m_type == eModuleSpecified) {
1120061da546Spatrick     s->Indent();
1121061da546Spatrick     if (m_module_sp) {
1122061da546Spatrick       m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX);
1123061da546Spatrick       s->Printf("Module: %s\n", path_str);
1124061da546Spatrick     } else
1125061da546Spatrick       s->Printf("Module: %s\n", m_module_spec.c_str());
1126061da546Spatrick   }
1127061da546Spatrick 
1128061da546Spatrick   if (m_type == eFileSpecified && m_file_spec_up != nullptr) {
1129061da546Spatrick     m_file_spec_up->GetPath(path_str, PATH_MAX);
1130061da546Spatrick     s->Indent();
1131061da546Spatrick     s->Printf("File: %s", path_str);
1132061da546Spatrick     if (m_type == eLineStartSpecified) {
1133061da546Spatrick       s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line);
1134061da546Spatrick       if (m_type == eLineEndSpecified)
1135061da546Spatrick         s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
1136061da546Spatrick       else
1137061da546Spatrick         s->Printf("to end");
1138061da546Spatrick     } else if (m_type == eLineEndSpecified) {
1139061da546Spatrick       s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line);
1140061da546Spatrick     }
1141061da546Spatrick     s->Printf(".\n");
1142061da546Spatrick   }
1143061da546Spatrick 
1144061da546Spatrick   if (m_type == eLineStartSpecified) {
1145061da546Spatrick     s->Indent();
1146061da546Spatrick     s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line);
1147061da546Spatrick     if (m_type == eLineEndSpecified)
1148061da546Spatrick       s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line);
1149061da546Spatrick     else
1150061da546Spatrick       s->Printf("to end");
1151061da546Spatrick     s->Printf(".\n");
1152061da546Spatrick   } else if (m_type == eLineEndSpecified) {
1153061da546Spatrick     s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line);
1154061da546Spatrick   }
1155061da546Spatrick 
1156061da546Spatrick   if (m_type == eFunctionSpecified) {
1157061da546Spatrick     s->Indent();
1158061da546Spatrick     s->Printf("Function: %s.\n", m_function_spec.c_str());
1159061da546Spatrick   }
1160061da546Spatrick 
1161061da546Spatrick   if (m_type == eClassOrNamespaceSpecified) {
1162061da546Spatrick     s->Indent();
1163061da546Spatrick     s->Printf("Class name: %s.\n", m_class_name.c_str());
1164061da546Spatrick   }
1165061da546Spatrick 
1166061da546Spatrick   if (m_type == eAddressRangeSpecified && m_address_range_up != nullptr) {
1167061da546Spatrick     s->Indent();
1168061da546Spatrick     s->PutCString("Address range: ");
1169061da546Spatrick     m_address_range_up->Dump(s, m_target_sp.get(),
1170061da546Spatrick                              Address::DumpStyleLoadAddress,
1171061da546Spatrick                              Address::DumpStyleFileAddress);
1172061da546Spatrick     s->PutCString("\n");
1173061da546Spatrick   }
1174061da546Spatrick }
1175061da546Spatrick 
1176061da546Spatrick //
1177061da546Spatrick //  SymbolContextList
1178061da546Spatrick //
1179061da546Spatrick 
SymbolContextList()1180061da546Spatrick SymbolContextList::SymbolContextList() : m_symbol_contexts() {}
1181061da546Spatrick 
1182be691f3bSpatrick SymbolContextList::~SymbolContextList() = default;
1183061da546Spatrick 
Append(const SymbolContext & sc)1184061da546Spatrick void SymbolContextList::Append(const SymbolContext &sc) {
1185061da546Spatrick   m_symbol_contexts.push_back(sc);
1186061da546Spatrick }
1187061da546Spatrick 
Append(const SymbolContextList & sc_list)1188061da546Spatrick void SymbolContextList::Append(const SymbolContextList &sc_list) {
1189061da546Spatrick   collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1190061da546Spatrick   for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
1191061da546Spatrick     m_symbol_contexts.push_back(*pos);
1192061da546Spatrick }
1193061da546Spatrick 
AppendIfUnique(const SymbolContextList & sc_list,bool merge_symbol_into_function)1194061da546Spatrick uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list,
1195061da546Spatrick                                            bool merge_symbol_into_function) {
1196061da546Spatrick   uint32_t unique_sc_add_count = 0;
1197061da546Spatrick   collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
1198061da546Spatrick   for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) {
1199061da546Spatrick     if (AppendIfUnique(*pos, merge_symbol_into_function))
1200061da546Spatrick       ++unique_sc_add_count;
1201061da546Spatrick   }
1202061da546Spatrick   return unique_sc_add_count;
1203061da546Spatrick }
1204061da546Spatrick 
AppendIfUnique(const SymbolContext & sc,bool merge_symbol_into_function)1205061da546Spatrick bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,
1206061da546Spatrick                                        bool merge_symbol_into_function) {
1207061da546Spatrick   collection::iterator pos, end = m_symbol_contexts.end();
1208061da546Spatrick   for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1209061da546Spatrick     if (*pos == sc)
1210061da546Spatrick       return false;
1211061da546Spatrick   }
1212061da546Spatrick   if (merge_symbol_into_function && sc.symbol != nullptr &&
1213061da546Spatrick       sc.comp_unit == nullptr && sc.function == nullptr &&
1214061da546Spatrick       sc.block == nullptr && !sc.line_entry.IsValid()) {
1215061da546Spatrick     if (sc.symbol->ValueIsAddress()) {
1216061da546Spatrick       for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1217061da546Spatrick         // Don't merge symbols into inlined function symbol contexts
1218061da546Spatrick         if (pos->block && pos->block->GetContainingInlinedBlock())
1219061da546Spatrick           continue;
1220061da546Spatrick 
1221061da546Spatrick         if (pos->function) {
1222061da546Spatrick           if (pos->function->GetAddressRange().GetBaseAddress() ==
1223061da546Spatrick               sc.symbol->GetAddressRef()) {
1224061da546Spatrick             // Do we already have a function with this symbol?
1225061da546Spatrick             if (pos->symbol == sc.symbol)
1226061da546Spatrick               return false;
1227061da546Spatrick             if (pos->symbol == nullptr) {
1228061da546Spatrick               pos->symbol = sc.symbol;
1229061da546Spatrick               return false;
1230061da546Spatrick             }
1231061da546Spatrick           }
1232061da546Spatrick         }
1233061da546Spatrick       }
1234061da546Spatrick     }
1235061da546Spatrick   }
1236061da546Spatrick   m_symbol_contexts.push_back(sc);
1237061da546Spatrick   return true;
1238061da546Spatrick }
1239061da546Spatrick 
Clear()1240061da546Spatrick void SymbolContextList::Clear() { m_symbol_contexts.clear(); }
1241061da546Spatrick 
Dump(Stream * s,Target * target) const1242061da546Spatrick void SymbolContextList::Dump(Stream *s, Target *target) const {
1243061da546Spatrick 
1244061da546Spatrick   *s << this << ": ";
1245061da546Spatrick   s->Indent();
1246061da546Spatrick   s->PutCString("SymbolContextList");
1247061da546Spatrick   s->EOL();
1248061da546Spatrick   s->IndentMore();
1249061da546Spatrick 
1250061da546Spatrick   collection::const_iterator pos, end = m_symbol_contexts.end();
1251061da546Spatrick   for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
1252061da546Spatrick     // pos->Dump(s, target);
1253061da546Spatrick     pos->GetDescription(s, eDescriptionLevelVerbose, target);
1254061da546Spatrick   }
1255061da546Spatrick   s->IndentLess();
1256061da546Spatrick }
1257061da546Spatrick 
GetContextAtIndex(size_t idx,SymbolContext & sc) const1258061da546Spatrick bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const {
1259061da546Spatrick   if (idx < m_symbol_contexts.size()) {
1260061da546Spatrick     sc = m_symbol_contexts[idx];
1261061da546Spatrick     return true;
1262061da546Spatrick   }
1263061da546Spatrick   return false;
1264061da546Spatrick }
1265061da546Spatrick 
RemoveContextAtIndex(size_t idx)1266061da546Spatrick bool SymbolContextList::RemoveContextAtIndex(size_t idx) {
1267061da546Spatrick   if (idx < m_symbol_contexts.size()) {
1268061da546Spatrick     m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1269061da546Spatrick     return true;
1270061da546Spatrick   }
1271061da546Spatrick   return false;
1272061da546Spatrick }
1273061da546Spatrick 
GetSize() const1274061da546Spatrick uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); }
1275061da546Spatrick 
IsEmpty() const1276061da546Spatrick bool SymbolContextList::IsEmpty() const { return m_symbol_contexts.empty(); }
1277061da546Spatrick 
NumLineEntriesWithLine(uint32_t line) const1278061da546Spatrick uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const {
1279061da546Spatrick   uint32_t match_count = 0;
1280061da546Spatrick   const size_t size = m_symbol_contexts.size();
1281061da546Spatrick   for (size_t idx = 0; idx < size; ++idx) {
1282061da546Spatrick     if (m_symbol_contexts[idx].line_entry.line == line)
1283061da546Spatrick       ++match_count;
1284061da546Spatrick   }
1285061da546Spatrick   return match_count;
1286061da546Spatrick }
1287061da546Spatrick 
GetDescription(Stream * s,lldb::DescriptionLevel level,Target * target) const1288061da546Spatrick void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level,
1289061da546Spatrick                                        Target *target) const {
1290061da546Spatrick   const size_t size = m_symbol_contexts.size();
1291061da546Spatrick   for (size_t idx = 0; idx < size; ++idx)
1292061da546Spatrick     m_symbol_contexts[idx].GetDescription(s, level, target);
1293061da546Spatrick }
1294061da546Spatrick 
operator ==(const SymbolContextList & lhs,const SymbolContextList & rhs)1295061da546Spatrick bool lldb_private::operator==(const SymbolContextList &lhs,
1296061da546Spatrick                               const SymbolContextList &rhs) {
1297061da546Spatrick   const uint32_t size = lhs.GetSize();
1298061da546Spatrick   if (size != rhs.GetSize())
1299061da546Spatrick     return false;
1300061da546Spatrick 
1301061da546Spatrick   SymbolContext lhs_sc;
1302061da546Spatrick   SymbolContext rhs_sc;
1303061da546Spatrick   for (uint32_t i = 0; i < size; ++i) {
1304061da546Spatrick     lhs.GetContextAtIndex(i, lhs_sc);
1305061da546Spatrick     rhs.GetContextAtIndex(i, rhs_sc);
1306061da546Spatrick     if (lhs_sc != rhs_sc)
1307061da546Spatrick       return false;
1308061da546Spatrick   }
1309061da546Spatrick   return true;
1310061da546Spatrick }
1311061da546Spatrick 
operator !=(const SymbolContextList & lhs,const SymbolContextList & rhs)1312061da546Spatrick bool lldb_private::operator!=(const SymbolContextList &lhs,
1313061da546Spatrick                               const SymbolContextList &rhs) {
1314061da546Spatrick   return !(lhs == rhs);
1315061da546Spatrick }
1316