1 //===-- Symtab.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <map>
10 #include <set>
11 
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/RichManglingContext.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Symbol/Symbol.h"
17 #include "lldb/Symbol/SymbolContext.h"
18 #include "lldb/Symbol/Symtab.h"
19 #include "lldb/Target/Language.h"
20 #include "lldb/Utility/RegularExpression.h"
21 #include "lldb/Utility/Stream.h"
22 #include "lldb/Utility/Timer.h"
23 
24 #include "llvm/ADT/StringRef.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
Symtab(ObjectFile * objfile)29 Symtab::Symtab(ObjectFile *objfile)
30     : m_objfile(objfile), m_symbols(), m_file_addr_to_index(*this),
31       m_name_to_symbol_indices(), m_mutex(),
32       m_file_addr_to_index_computed(false), m_name_indexes_computed(false) {
33   m_name_to_symbol_indices.emplace(std::make_pair(
34       lldb::eFunctionNameTypeNone, UniqueCStringMap<uint32_t>()));
35   m_name_to_symbol_indices.emplace(std::make_pair(
36       lldb::eFunctionNameTypeBase, UniqueCStringMap<uint32_t>()));
37   m_name_to_symbol_indices.emplace(std::make_pair(
38       lldb::eFunctionNameTypeMethod, UniqueCStringMap<uint32_t>()));
39   m_name_to_symbol_indices.emplace(std::make_pair(
40       lldb::eFunctionNameTypeSelector, UniqueCStringMap<uint32_t>()));
41 }
42 
43 Symtab::~Symtab() = default;
44 
Reserve(size_t count)45 void Symtab::Reserve(size_t count) {
46   // Clients should grab the mutex from this symbol table and lock it manually
47   // when calling this function to avoid performance issues.
48   m_symbols.reserve(count);
49 }
50 
Resize(size_t count)51 Symbol *Symtab::Resize(size_t count) {
52   // Clients should grab the mutex from this symbol table and lock it manually
53   // when calling this function to avoid performance issues.
54   m_symbols.resize(count);
55   return m_symbols.empty() ? nullptr : &m_symbols[0];
56 }
57 
AddSymbol(const Symbol & symbol)58 uint32_t Symtab::AddSymbol(const Symbol &symbol) {
59   // Clients should grab the mutex from this symbol table and lock it manually
60   // when calling this function to avoid performance issues.
61   uint32_t symbol_idx = m_symbols.size();
62   auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
63   name_to_index.Clear();
64   m_file_addr_to_index.Clear();
65   m_symbols.push_back(symbol);
66   m_file_addr_to_index_computed = false;
67   m_name_indexes_computed = false;
68   return symbol_idx;
69 }
70 
GetNumSymbols() const71 size_t Symtab::GetNumSymbols() const {
72   std::lock_guard<std::recursive_mutex> guard(m_mutex);
73   return m_symbols.size();
74 }
75 
SectionFileAddressesChanged()76 void Symtab::SectionFileAddressesChanged() {
77   auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
78   name_to_index.Clear();
79   m_file_addr_to_index_computed = false;
80 }
81 
Dump(Stream * s,Target * target,SortOrder sort_order,Mangled::NamePreference name_preference)82 void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order,
83                   Mangled::NamePreference name_preference) {
84   std::lock_guard<std::recursive_mutex> guard(m_mutex);
85 
86   //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
87   s->Indent();
88   const FileSpec &file_spec = m_objfile->GetFileSpec();
89   const char *object_name = nullptr;
90   if (m_objfile->GetModule())
91     object_name = m_objfile->GetModule()->GetObjectName().GetCString();
92 
93   if (file_spec)
94     s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64,
95               file_spec.GetPath().c_str(), object_name ? "(" : "",
96               object_name ? object_name : "", object_name ? ")" : "",
97               (uint64_t)m_symbols.size());
98   else
99     s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size());
100 
101   if (!m_symbols.empty()) {
102     switch (sort_order) {
103     case eSortOrderNone: {
104       s->PutCString(":\n");
105       DumpSymbolHeader(s);
106       const_iterator begin = m_symbols.begin();
107       const_iterator end = m_symbols.end();
108       for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
109         s->Indent();
110         pos->Dump(s, target, std::distance(begin, pos), name_preference);
111       }
112     } break;
113 
114     case eSortOrderByName: {
115       // Although we maintain a lookup by exact name map, the table isn't
116       // sorted by name. So we must make the ordered symbol list up ourselves.
117       s->PutCString(" (sorted by name):\n");
118       DumpSymbolHeader(s);
119 
120       std::multimap<llvm::StringRef, const Symbol *> name_map;
121       for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
122            pos != end; ++pos) {
123         const char *name = pos->GetName().AsCString();
124         if (name && name[0])
125           name_map.insert(std::make_pair(name, &(*pos)));
126       }
127 
128       for (const auto &name_to_symbol : name_map) {
129         const Symbol *symbol = name_to_symbol.second;
130         s->Indent();
131         symbol->Dump(s, target, symbol - &m_symbols[0], name_preference);
132       }
133     } break;
134 
135     case eSortOrderByAddress:
136       s->PutCString(" (sorted by address):\n");
137       DumpSymbolHeader(s);
138       if (!m_file_addr_to_index_computed)
139         InitAddressIndexes();
140       const size_t num_entries = m_file_addr_to_index.GetSize();
141       for (size_t i = 0; i < num_entries; ++i) {
142         s->Indent();
143         const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
144         m_symbols[symbol_idx].Dump(s, target, symbol_idx, name_preference);
145       }
146       break;
147     }
148   } else {
149     s->PutCString("\n");
150   }
151 }
152 
Dump(Stream * s,Target * target,std::vector<uint32_t> & indexes,Mangled::NamePreference name_preference) const153 void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
154                   Mangled::NamePreference name_preference) const {
155   std::lock_guard<std::recursive_mutex> guard(m_mutex);
156 
157   const size_t num_symbols = GetNumSymbols();
158   // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
159   s->Indent();
160   s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n",
161             (uint64_t)indexes.size(), (uint64_t)m_symbols.size());
162   s->IndentMore();
163 
164   if (!indexes.empty()) {
165     std::vector<uint32_t>::const_iterator pos;
166     std::vector<uint32_t>::const_iterator end = indexes.end();
167     DumpSymbolHeader(s);
168     for (pos = indexes.begin(); pos != end; ++pos) {
169       size_t idx = *pos;
170       if (idx < num_symbols) {
171         s->Indent();
172         m_symbols[idx].Dump(s, target, idx, name_preference);
173       }
174     }
175   }
176   s->IndentLess();
177 }
178 
DumpSymbolHeader(Stream * s)179 void Symtab::DumpSymbolHeader(Stream *s) {
180   s->Indent("               Debug symbol\n");
181   s->Indent("               |Synthetic symbol\n");
182   s->Indent("               ||Externally Visible\n");
183   s->Indent("               |||\n");
184   s->Indent("Index   UserID DSX Type            File Address/Value Load "
185             "Address       Size               Flags      Name\n");
186   s->Indent("------- ------ --- --------------- ------------------ "
187             "------------------ ------------------ ---------- "
188             "----------------------------------\n");
189 }
190 
CompareSymbolID(const void * key,const void * p)191 static int CompareSymbolID(const void *key, const void *p) {
192   const user_id_t match_uid = *(const user_id_t *)key;
193   const user_id_t symbol_uid = ((const Symbol *)p)->GetID();
194   if (match_uid < symbol_uid)
195     return -1;
196   if (match_uid > symbol_uid)
197     return 1;
198   return 0;
199 }
200 
FindSymbolByID(lldb::user_id_t symbol_uid) const201 Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const {
202   std::lock_guard<std::recursive_mutex> guard(m_mutex);
203 
204   Symbol *symbol =
205       (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(),
206                           sizeof(m_symbols[0]), CompareSymbolID);
207   return symbol;
208 }
209 
SymbolAtIndex(size_t idx)210 Symbol *Symtab::SymbolAtIndex(size_t idx) {
211   // Clients should grab the mutex from this symbol table and lock it manually
212   // when calling this function to avoid performance issues.
213   if (idx < m_symbols.size())
214     return &m_symbols[idx];
215   return nullptr;
216 }
217 
SymbolAtIndex(size_t idx) const218 const Symbol *Symtab::SymbolAtIndex(size_t idx) const {
219   // Clients should grab the mutex from this symbol table and lock it manually
220   // when calling this function to avoid performance issues.
221   if (idx < m_symbols.size())
222     return &m_symbols[idx];
223   return nullptr;
224 }
225 
lldb_skip_name(llvm::StringRef mangled,Mangled::ManglingScheme scheme)226 static bool lldb_skip_name(llvm::StringRef mangled,
227                            Mangled::ManglingScheme scheme) {
228   switch (scheme) {
229   case Mangled::eManglingSchemeItanium: {
230     if (mangled.size() < 3 || !mangled.startswith("_Z"))
231       return true;
232 
233     // Avoid the following types of symbols in the index.
234     switch (mangled[2]) {
235     case 'G': // guard variables
236     case 'T': // virtual tables, VTT structures, typeinfo structures + names
237     case 'Z': // named local entities (if we eventually handle
238               // eSymbolTypeData, we will want this back)
239       return true;
240 
241     default:
242       break;
243     }
244 
245     // Include this name in the index.
246     return false;
247   }
248 
249   // No filters for this scheme yet. Include all names in indexing.
250   case Mangled::eManglingSchemeMSVC:
251     return false;
252 
253   // No filters for this scheme yet. Include all names in indexing.
254   case Mangled::eManglingSchemeRustV0:
255     return false;
256 
257   // Don't try and demangle things we can't categorize.
258   case Mangled::eManglingSchemeNone:
259     return true;
260   }
261   llvm_unreachable("unknown scheme!");
262 }
263 
InitNameIndexes()264 void Symtab::InitNameIndexes() {
265   // Protected function, no need to lock mutex...
266   if (!m_name_indexes_computed) {
267     m_name_indexes_computed = true;
268     LLDB_SCOPED_TIMER();
269 
270     // Collect all loaded language plugins.
271     std::vector<Language *> languages;
272     Language::ForEach([&languages](Language *l) {
273       languages.push_back(l);
274       return true;
275     });
276 
277     auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
278     auto &basename_to_index =
279         GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
280     auto &method_to_index =
281         GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
282     auto &selector_to_index =
283         GetNameToSymbolIndexMap(lldb::eFunctionNameTypeSelector);
284     // Create the name index vector to be able to quickly search by name
285     const size_t num_symbols = m_symbols.size();
286     name_to_index.Reserve(num_symbols);
287 
288     // The "const char *" in "class_contexts" and backlog::value_type::second
289     // must come from a ConstString::GetCString()
290     std::set<const char *> class_contexts;
291     std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog;
292     backlog.reserve(num_symbols / 2);
293 
294     // Instantiation of the demangler is expensive, so better use a single one
295     // for all entries during batch processing.
296     RichManglingContext rmc;
297     for (uint32_t value = 0; value < num_symbols; ++value) {
298       Symbol *symbol = &m_symbols[value];
299 
300       // Don't let trampolines get into the lookup by name map If we ever need
301       // the trampoline symbols to be searchable by name we can remove this and
302       // then possibly add a new bool to any of the Symtab functions that
303       // lookup symbols by name to indicate if they want trampolines. We also
304       // don't want any synthetic symbols with auto generated names in the
305       // name lookups.
306       if (symbol->IsTrampoline() || symbol->IsSyntheticWithAutoGeneratedName())
307         continue;
308 
309       // If the symbol's name string matched a Mangled::ManglingScheme, it is
310       // stored in the mangled field.
311       Mangled &mangled = symbol->GetMangled();
312       if (ConstString name = mangled.GetMangledName()) {
313         name_to_index.Append(name, value);
314 
315         if (symbol->ContainsLinkerAnnotations()) {
316           // If the symbol has linker annotations, also add the version without
317           // the annotations.
318           ConstString stripped = ConstString(
319               m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
320           name_to_index.Append(stripped, value);
321         }
322 
323         const SymbolType type = symbol->GetType();
324         if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
325           if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name))
326             RegisterMangledNameEntry(value, class_contexts, backlog, rmc);
327         }
328       }
329 
330       // Symbol name strings that didn't match a Mangled::ManglingScheme, are
331       // stored in the demangled field.
332       if (ConstString name = mangled.GetDemangledName()) {
333         name_to_index.Append(name, value);
334 
335         if (symbol->ContainsLinkerAnnotations()) {
336           // If the symbol has linker annotations, also add the version without
337           // the annotations.
338           name = ConstString(
339               m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
340           name_to_index.Append(name, value);
341         }
342 
343         // If the demangled name turns out to be an ObjC name, and is a category
344         // name, add the version without categories to the index too.
345         for (Language *lang : languages) {
346           for (auto variant : lang->GetMethodNameVariants(name)) {
347             if (variant.GetType() & lldb::eFunctionNameTypeSelector)
348               selector_to_index.Append(variant.GetName(), value);
349             else if (variant.GetType() & lldb::eFunctionNameTypeFull)
350               name_to_index.Append(variant.GetName(), value);
351             else if (variant.GetType() & lldb::eFunctionNameTypeMethod)
352               method_to_index.Append(variant.GetName(), value);
353             else if (variant.GetType() & lldb::eFunctionNameTypeBase)
354               basename_to_index.Append(variant.GetName(), value);
355           }
356         }
357       }
358     }
359 
360     for (const auto &record : backlog) {
361       RegisterBacklogEntry(record.first, record.second, class_contexts);
362     }
363 
364     name_to_index.Sort();
365     name_to_index.SizeToFit();
366     selector_to_index.Sort();
367     selector_to_index.SizeToFit();
368     basename_to_index.Sort();
369     basename_to_index.SizeToFit();
370     method_to_index.Sort();
371     method_to_index.SizeToFit();
372   }
373 }
374 
RegisterMangledNameEntry(uint32_t value,std::set<const char * > & class_contexts,std::vector<std::pair<NameToIndexMap::Entry,const char * >> & backlog,RichManglingContext & rmc)375 void Symtab::RegisterMangledNameEntry(
376     uint32_t value, std::set<const char *> &class_contexts,
377     std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
378     RichManglingContext &rmc) {
379   // Only register functions that have a base name.
380   rmc.ParseFunctionBaseName();
381   llvm::StringRef base_name = rmc.GetBufferRef();
382   if (base_name.empty())
383     return;
384 
385   // The base name will be our entry's name.
386   NameToIndexMap::Entry entry(ConstString(base_name), value);
387 
388   rmc.ParseFunctionDeclContextName();
389   llvm::StringRef decl_context = rmc.GetBufferRef();
390 
391   // Register functions with no context.
392   if (decl_context.empty()) {
393     // This has to be a basename
394     auto &basename_to_index =
395         GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
396     basename_to_index.Append(entry);
397     // If there is no context (no namespaces or class scopes that come before
398     // the function name) then this also could be a fullname.
399     auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
400     name_to_index.Append(entry);
401     return;
402   }
403 
404   // Make sure we have a pool-string pointer and see if we already know the
405   // context name.
406   const char *decl_context_ccstr = ConstString(decl_context).GetCString();
407   auto it = class_contexts.find(decl_context_ccstr);
408 
409   auto &method_to_index =
410       GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
411   // Register constructors and destructors. They are methods and create
412   // declaration contexts.
413   if (rmc.IsCtorOrDtor()) {
414     method_to_index.Append(entry);
415     if (it == class_contexts.end())
416       class_contexts.insert(it, decl_context_ccstr);
417     return;
418   }
419 
420   // Register regular methods with a known declaration context.
421   if (it != class_contexts.end()) {
422     method_to_index.Append(entry);
423     return;
424   }
425 
426   // Regular methods in unknown declaration contexts are put to the backlog. We
427   // will revisit them once we processed all remaining symbols.
428   backlog.push_back(std::make_pair(entry, decl_context_ccstr));
429 }
430 
RegisterBacklogEntry(const NameToIndexMap::Entry & entry,const char * decl_context,const std::set<const char * > & class_contexts)431 void Symtab::RegisterBacklogEntry(
432     const NameToIndexMap::Entry &entry, const char *decl_context,
433     const std::set<const char *> &class_contexts) {
434   auto &method_to_index =
435       GetNameToSymbolIndexMap(lldb::eFunctionNameTypeMethod);
436   auto it = class_contexts.find(decl_context);
437   if (it != class_contexts.end()) {
438     method_to_index.Append(entry);
439   } else {
440     // If we got here, we have something that had a context (was inside
441     // a namespace or class) yet we don't know the entry
442     method_to_index.Append(entry);
443     auto &basename_to_index =
444         GetNameToSymbolIndexMap(lldb::eFunctionNameTypeBase);
445     basename_to_index.Append(entry);
446   }
447 }
448 
PreloadSymbols()449 void Symtab::PreloadSymbols() {
450   std::lock_guard<std::recursive_mutex> guard(m_mutex);
451   InitNameIndexes();
452 }
453 
AppendSymbolNamesToMap(const IndexCollection & indexes,bool add_demangled,bool add_mangled,NameToIndexMap & name_to_index_map) const454 void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes,
455                                     bool add_demangled, bool add_mangled,
456                                     NameToIndexMap &name_to_index_map) const {
457   LLDB_SCOPED_TIMER();
458   if (add_demangled || add_mangled) {
459     std::lock_guard<std::recursive_mutex> guard(m_mutex);
460 
461     // Create the name index vector to be able to quickly search by name
462     const size_t num_indexes = indexes.size();
463     for (size_t i = 0; i < num_indexes; ++i) {
464       uint32_t value = indexes[i];
465       assert(i < m_symbols.size());
466       const Symbol *symbol = &m_symbols[value];
467 
468       const Mangled &mangled = symbol->GetMangled();
469       if (add_demangled) {
470         if (ConstString name = mangled.GetDemangledName())
471           name_to_index_map.Append(name, value);
472       }
473 
474       if (add_mangled) {
475         if (ConstString name = mangled.GetMangledName())
476           name_to_index_map.Append(name, value);
477       }
478     }
479   }
480 }
481 
AppendSymbolIndexesWithType(SymbolType symbol_type,std::vector<uint32_t> & indexes,uint32_t start_idx,uint32_t end_index) const482 uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type,
483                                              std::vector<uint32_t> &indexes,
484                                              uint32_t start_idx,
485                                              uint32_t end_index) const {
486   std::lock_guard<std::recursive_mutex> guard(m_mutex);
487 
488   uint32_t prev_size = indexes.size();
489 
490   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
491 
492   for (uint32_t i = start_idx; i < count; ++i) {
493     if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
494       indexes.push_back(i);
495   }
496 
497   return indexes.size() - prev_size;
498 }
499 
AppendSymbolIndexesWithTypeAndFlagsValue(SymbolType symbol_type,uint32_t flags_value,std::vector<uint32_t> & indexes,uint32_t start_idx,uint32_t end_index) const500 uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue(
501     SymbolType symbol_type, uint32_t flags_value,
502     std::vector<uint32_t> &indexes, uint32_t start_idx,
503     uint32_t end_index) const {
504   std::lock_guard<std::recursive_mutex> guard(m_mutex);
505 
506   uint32_t prev_size = indexes.size();
507 
508   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
509 
510   for (uint32_t i = start_idx; i < count; ++i) {
511     if ((symbol_type == eSymbolTypeAny ||
512          m_symbols[i].GetType() == symbol_type) &&
513         m_symbols[i].GetFlags() == flags_value)
514       indexes.push_back(i);
515   }
516 
517   return indexes.size() - prev_size;
518 }
519 
AppendSymbolIndexesWithType(SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & indexes,uint32_t start_idx,uint32_t end_index) const520 uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type,
521                                              Debug symbol_debug_type,
522                                              Visibility symbol_visibility,
523                                              std::vector<uint32_t> &indexes,
524                                              uint32_t start_idx,
525                                              uint32_t end_index) const {
526   std::lock_guard<std::recursive_mutex> guard(m_mutex);
527 
528   uint32_t prev_size = indexes.size();
529 
530   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
531 
532   for (uint32_t i = start_idx; i < count; ++i) {
533     if (symbol_type == eSymbolTypeAny ||
534         m_symbols[i].GetType() == symbol_type) {
535       if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
536         indexes.push_back(i);
537     }
538   }
539 
540   return indexes.size() - prev_size;
541 }
542 
GetIndexForSymbol(const Symbol * symbol) const543 uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const {
544   if (!m_symbols.empty()) {
545     const Symbol *first_symbol = &m_symbols[0];
546     if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
547       return symbol - first_symbol;
548   }
549   return UINT32_MAX;
550 }
551 
552 struct SymbolSortInfo {
553   const bool sort_by_load_addr;
554   const Symbol *symbols;
555 };
556 
557 namespace {
558 struct SymbolIndexComparator {
559   const std::vector<Symbol> &symbols;
560   std::vector<lldb::addr_t> &addr_cache;
561 
562   // Getting from the symbol to the Address to the File Address involves some
563   // work. Since there are potentially many symbols here, and we're using this
564   // for sorting so we're going to be computing the address many times, cache
565   // that in addr_cache. The array passed in has to be the same size as the
566   // symbols array passed into the member variable symbols, and should be
567   // initialized with LLDB_INVALID_ADDRESS.
568   // NOTE: You have to make addr_cache externally and pass it in because
569   // std::stable_sort
570   // makes copies of the comparator it is initially passed in, and you end up
571   // spending huge amounts of time copying this array...
572 
SymbolIndexComparator__anon624de55d0211::SymbolIndexComparator573   SymbolIndexComparator(const std::vector<Symbol> &s,
574                         std::vector<lldb::addr_t> &a)
575       : symbols(s), addr_cache(a) {
576     assert(symbols.size() == addr_cache.size());
577   }
operator ()__anon624de55d0211::SymbolIndexComparator578   bool operator()(uint32_t index_a, uint32_t index_b) {
579     addr_t value_a = addr_cache[index_a];
580     if (value_a == LLDB_INVALID_ADDRESS) {
581       value_a = symbols[index_a].GetAddressRef().GetFileAddress();
582       addr_cache[index_a] = value_a;
583     }
584 
585     addr_t value_b = addr_cache[index_b];
586     if (value_b == LLDB_INVALID_ADDRESS) {
587       value_b = symbols[index_b].GetAddressRef().GetFileAddress();
588       addr_cache[index_b] = value_b;
589     }
590 
591     if (value_a == value_b) {
592       // The if the values are equal, use the original symbol user ID
593       lldb::user_id_t uid_a = symbols[index_a].GetID();
594       lldb::user_id_t uid_b = symbols[index_b].GetID();
595       if (uid_a < uid_b)
596         return true;
597       if (uid_a > uid_b)
598         return false;
599       return false;
600     } else if (value_a < value_b)
601       return true;
602 
603     return false;
604   }
605 };
606 }
607 
SortSymbolIndexesByValue(std::vector<uint32_t> & indexes,bool remove_duplicates) const608 void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
609                                       bool remove_duplicates) const {
610   std::lock_guard<std::recursive_mutex> guard(m_mutex);
611   LLDB_SCOPED_TIMER();
612   // No need to sort if we have zero or one items...
613   if (indexes.size() <= 1)
614     return;
615 
616   // Sort the indexes in place using std::stable_sort.
617   // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly
618   // for performance, not correctness.  The indexes vector tends to be "close"
619   // to sorted, which the stable sort handles better.
620 
621   std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
622 
623   SymbolIndexComparator comparator(m_symbols, addr_cache);
624   std::stable_sort(indexes.begin(), indexes.end(), comparator);
625 
626   // Remove any duplicates if requested
627   if (remove_duplicates) {
628     auto last = std::unique(indexes.begin(), indexes.end());
629     indexes.erase(last, indexes.end());
630   }
631 }
632 
GetNameIndexes(ConstString symbol_name,std::vector<uint32_t> & indexes)633 uint32_t Symtab::GetNameIndexes(ConstString symbol_name,
634                                 std::vector<uint32_t> &indexes) {
635   auto &name_to_index = GetNameToSymbolIndexMap(lldb::eFunctionNameTypeNone);
636   const uint32_t count = name_to_index.GetValues(symbol_name, indexes);
637   if (count)
638     return count;
639   // Synthetic symbol names are not added to the name indexes, but they start
640   // with a prefix and end with a the symbol UserID. This allows users to find
641   // these symbols without having to add them to the name indexes. These
642   // queries will not happen very often since the names don't mean anything, so
643   // performance is not paramount in this case.
644   llvm::StringRef name = symbol_name.GetStringRef();
645   // String the synthetic prefix if the name starts with it.
646   if (!name.consume_front(Symbol::GetSyntheticSymbolPrefix()))
647     return 0; // Not a synthetic symbol name
648 
649   // Extract the user ID from the symbol name
650   unsigned long long uid = 0;
651   if (getAsUnsignedInteger(name, /*Radix=*/10, uid))
652     return 0; // Failed to extract the user ID as an integer
653   Symbol *symbol = FindSymbolByID(uid);
654   if (symbol == nullptr)
655     return 0;
656   const uint32_t symbol_idx = GetIndexForSymbol(symbol);
657   if (symbol_idx == UINT32_MAX)
658     return 0;
659   indexes.push_back(symbol_idx);
660   return 1;
661 }
662 
AppendSymbolIndexesWithName(ConstString symbol_name,std::vector<uint32_t> & indexes)663 uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
664                                              std::vector<uint32_t> &indexes) {
665   std::lock_guard<std::recursive_mutex> guard(m_mutex);
666 
667   LLDB_SCOPED_TIMER();
668   if (symbol_name) {
669     if (!m_name_indexes_computed)
670       InitNameIndexes();
671 
672     return GetNameIndexes(symbol_name, indexes);
673   }
674   return 0;
675 }
676 
AppendSymbolIndexesWithName(ConstString symbol_name,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & indexes)677 uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
678                                              Debug symbol_debug_type,
679                                              Visibility symbol_visibility,
680                                              std::vector<uint32_t> &indexes) {
681   std::lock_guard<std::recursive_mutex> guard(m_mutex);
682 
683   LLDB_SCOPED_TIMER();
684   if (symbol_name) {
685     const size_t old_size = indexes.size();
686     if (!m_name_indexes_computed)
687       InitNameIndexes();
688 
689     std::vector<uint32_t> all_name_indexes;
690     const size_t name_match_count =
691         GetNameIndexes(symbol_name, all_name_indexes);
692     for (size_t i = 0; i < name_match_count; ++i) {
693       if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type,
694                              symbol_visibility))
695         indexes.push_back(all_name_indexes[i]);
696     }
697     return indexes.size() - old_size;
698   }
699   return 0;
700 }
701 
702 uint32_t
AppendSymbolIndexesWithNameAndType(ConstString symbol_name,SymbolType symbol_type,std::vector<uint32_t> & indexes)703 Symtab::AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
704                                            SymbolType symbol_type,
705                                            std::vector<uint32_t> &indexes) {
706   std::lock_guard<std::recursive_mutex> guard(m_mutex);
707 
708   if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) {
709     std::vector<uint32_t>::iterator pos = indexes.begin();
710     while (pos != indexes.end()) {
711       if (symbol_type == eSymbolTypeAny ||
712           m_symbols[*pos].GetType() == symbol_type)
713         ++pos;
714       else
715         pos = indexes.erase(pos);
716     }
717   }
718   return indexes.size();
719 }
720 
AppendSymbolIndexesWithNameAndType(ConstString symbol_name,SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & indexes)721 uint32_t Symtab::AppendSymbolIndexesWithNameAndType(
722     ConstString symbol_name, SymbolType symbol_type,
723     Debug symbol_debug_type, Visibility symbol_visibility,
724     std::vector<uint32_t> &indexes) {
725   std::lock_guard<std::recursive_mutex> guard(m_mutex);
726 
727   if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type,
728                                   symbol_visibility, indexes) > 0) {
729     std::vector<uint32_t>::iterator pos = indexes.begin();
730     while (pos != indexes.end()) {
731       if (symbol_type == eSymbolTypeAny ||
732           m_symbols[*pos].GetType() == symbol_type)
733         ++pos;
734       else
735         pos = indexes.erase(pos);
736     }
737   }
738   return indexes.size();
739 }
740 
AppendSymbolIndexesMatchingRegExAndType(const RegularExpression & regexp,SymbolType symbol_type,std::vector<uint32_t> & indexes)741 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
742     const RegularExpression &regexp, SymbolType symbol_type,
743     std::vector<uint32_t> &indexes) {
744   std::lock_guard<std::recursive_mutex> guard(m_mutex);
745 
746   uint32_t prev_size = indexes.size();
747   uint32_t sym_end = m_symbols.size();
748 
749   for (uint32_t i = 0; i < sym_end; i++) {
750     if (symbol_type == eSymbolTypeAny ||
751         m_symbols[i].GetType() == symbol_type) {
752       const char *name = m_symbols[i].GetName().AsCString();
753       if (name) {
754         if (regexp.Execute(name))
755           indexes.push_back(i);
756       }
757     }
758   }
759   return indexes.size() - prev_size;
760 }
761 
AppendSymbolIndexesMatchingRegExAndType(const RegularExpression & regexp,SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & indexes)762 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
763     const RegularExpression &regexp, SymbolType symbol_type,
764     Debug symbol_debug_type, Visibility symbol_visibility,
765     std::vector<uint32_t> &indexes) {
766   std::lock_guard<std::recursive_mutex> guard(m_mutex);
767 
768   uint32_t prev_size = indexes.size();
769   uint32_t sym_end = m_symbols.size();
770 
771   for (uint32_t i = 0; i < sym_end; i++) {
772     if (symbol_type == eSymbolTypeAny ||
773         m_symbols[i].GetType() == symbol_type) {
774       if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
775         continue;
776 
777       const char *name = m_symbols[i].GetName().AsCString();
778       if (name) {
779         if (regexp.Execute(name))
780           indexes.push_back(i);
781       }
782     }
783   }
784   return indexes.size() - prev_size;
785 }
786 
FindSymbolWithType(SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,uint32_t & start_idx)787 Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type,
788                                    Debug symbol_debug_type,
789                                    Visibility symbol_visibility,
790                                    uint32_t &start_idx) {
791   std::lock_guard<std::recursive_mutex> guard(m_mutex);
792 
793   const size_t count = m_symbols.size();
794   for (size_t idx = start_idx; idx < count; ++idx) {
795     if (symbol_type == eSymbolTypeAny ||
796         m_symbols[idx].GetType() == symbol_type) {
797       if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) {
798         start_idx = idx;
799         return &m_symbols[idx];
800       }
801     }
802   }
803   return nullptr;
804 }
805 
806 void
FindAllSymbolsWithNameAndType(ConstString name,SymbolType symbol_type,std::vector<uint32_t> & symbol_indexes)807 Symtab::FindAllSymbolsWithNameAndType(ConstString name,
808                                       SymbolType symbol_type,
809                                       std::vector<uint32_t> &symbol_indexes) {
810   std::lock_guard<std::recursive_mutex> guard(m_mutex);
811 
812   LLDB_SCOPED_TIMER();
813   // Initialize all of the lookup by name indexes before converting NAME to a
814   // uniqued string NAME_STR below.
815   if (!m_name_indexes_computed)
816     InitNameIndexes();
817 
818   if (name) {
819     // The string table did have a string that matched, but we need to check
820     // the symbols and match the symbol_type if any was given.
821     AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
822   }
823 }
824 
FindAllSymbolsWithNameAndType(ConstString name,SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & symbol_indexes)825 void Symtab::FindAllSymbolsWithNameAndType(
826     ConstString name, SymbolType symbol_type, Debug symbol_debug_type,
827     Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) {
828   std::lock_guard<std::recursive_mutex> guard(m_mutex);
829 
830   LLDB_SCOPED_TIMER();
831   // Initialize all of the lookup by name indexes before converting NAME to a
832   // uniqued string NAME_STR below.
833   if (!m_name_indexes_computed)
834     InitNameIndexes();
835 
836   if (name) {
837     // The string table did have a string that matched, but we need to check
838     // the symbols and match the symbol_type if any was given.
839     AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
840                                        symbol_visibility, symbol_indexes);
841   }
842 }
843 
FindAllSymbolsMatchingRexExAndType(const RegularExpression & regex,SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility,std::vector<uint32_t> & symbol_indexes)844 void Symtab::FindAllSymbolsMatchingRexExAndType(
845     const RegularExpression &regex, SymbolType symbol_type,
846     Debug symbol_debug_type, Visibility symbol_visibility,
847     std::vector<uint32_t> &symbol_indexes) {
848   std::lock_guard<std::recursive_mutex> guard(m_mutex);
849 
850   AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type,
851                                           symbol_visibility, symbol_indexes);
852 }
853 
FindFirstSymbolWithNameAndType(ConstString name,SymbolType symbol_type,Debug symbol_debug_type,Visibility symbol_visibility)854 Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name,
855                                                SymbolType symbol_type,
856                                                Debug symbol_debug_type,
857                                                Visibility symbol_visibility) {
858   std::lock_guard<std::recursive_mutex> guard(m_mutex);
859   LLDB_SCOPED_TIMER();
860   if (!m_name_indexes_computed)
861     InitNameIndexes();
862 
863   if (name) {
864     std::vector<uint32_t> matching_indexes;
865     // The string table did have a string that matched, but we need to check
866     // the symbols and match the symbol_type if any was given.
867     if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
868                                            symbol_visibility,
869                                            matching_indexes)) {
870       std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
871       for (pos = matching_indexes.begin(); pos != end; ++pos) {
872         Symbol *symbol = SymbolAtIndex(*pos);
873 
874         if (symbol->Compare(name, symbol_type))
875           return symbol;
876       }
877     }
878   }
879   return nullptr;
880 }
881 
882 typedef struct {
883   const Symtab *symtab;
884   const addr_t file_addr;
885   Symbol *match_symbol;
886   const uint32_t *match_index_ptr;
887   addr_t match_offset;
888 } SymbolSearchInfo;
889 
890 // Add all the section file start address & size to the RangeVector, recusively
891 // adding any children sections.
AddSectionsToRangeMap(SectionList * sectlist,RangeVector<addr_t,addr_t> & section_ranges)892 static void AddSectionsToRangeMap(SectionList *sectlist,
893                                   RangeVector<addr_t, addr_t> &section_ranges) {
894   const int num_sections = sectlist->GetNumSections(0);
895   for (int i = 0; i < num_sections; i++) {
896     SectionSP sect_sp = sectlist->GetSectionAtIndex(i);
897     if (sect_sp) {
898       SectionList &child_sectlist = sect_sp->GetChildren();
899 
900       // If this section has children, add the children to the RangeVector.
901       // Else add this section to the RangeVector.
902       if (child_sectlist.GetNumSections(0) > 0) {
903         AddSectionsToRangeMap(&child_sectlist, section_ranges);
904       } else {
905         size_t size = sect_sp->GetByteSize();
906         if (size > 0) {
907           addr_t base_addr = sect_sp->GetFileAddress();
908           RangeVector<addr_t, addr_t>::Entry entry;
909           entry.SetRangeBase(base_addr);
910           entry.SetByteSize(size);
911           section_ranges.Append(entry);
912         }
913       }
914     }
915   }
916 }
917 
InitAddressIndexes()918 void Symtab::InitAddressIndexes() {
919   // Protected function, no need to lock mutex...
920   if (!m_file_addr_to_index_computed && !m_symbols.empty()) {
921     m_file_addr_to_index_computed = true;
922 
923     FileRangeToIndexMap::Entry entry;
924     const_iterator begin = m_symbols.begin();
925     const_iterator end = m_symbols.end();
926     for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
927       if (pos->ValueIsAddress()) {
928         entry.SetRangeBase(pos->GetAddressRef().GetFileAddress());
929         entry.SetByteSize(pos->GetByteSize());
930         entry.data = std::distance(begin, pos);
931         m_file_addr_to_index.Append(entry);
932       }
933     }
934     const size_t num_entries = m_file_addr_to_index.GetSize();
935     if (num_entries > 0) {
936       m_file_addr_to_index.Sort();
937 
938       // Create a RangeVector with the start & size of all the sections for
939       // this objfile.  We'll need to check this for any FileRangeToIndexMap
940       // entries with an uninitialized size, which could potentially be a large
941       // number so reconstituting the weak pointer is busywork when it is
942       // invariant information.
943       SectionList *sectlist = m_objfile->GetSectionList();
944       RangeVector<addr_t, addr_t> section_ranges;
945       if (sectlist) {
946         AddSectionsToRangeMap(sectlist, section_ranges);
947         section_ranges.Sort();
948       }
949 
950       // Iterate through the FileRangeToIndexMap and fill in the size for any
951       // entries that didn't already have a size from the Symbol (e.g. if we
952       // have a plain linker symbol with an address only, instead of debug info
953       // where we get an address and a size and a type, etc.)
954       for (size_t i = 0; i < num_entries; i++) {
955         FileRangeToIndexMap::Entry *entry =
956             m_file_addr_to_index.GetMutableEntryAtIndex(i);
957         if (entry->GetByteSize() == 0) {
958           addr_t curr_base_addr = entry->GetRangeBase();
959           const RangeVector<addr_t, addr_t>::Entry *containing_section =
960               section_ranges.FindEntryThatContains(curr_base_addr);
961 
962           // Use the end of the section as the default max size of the symbol
963           addr_t sym_size = 0;
964           if (containing_section) {
965             sym_size =
966                 containing_section->GetByteSize() -
967                 (entry->GetRangeBase() - containing_section->GetRangeBase());
968           }
969 
970           for (size_t j = i; j < num_entries; j++) {
971             FileRangeToIndexMap::Entry *next_entry =
972                 m_file_addr_to_index.GetMutableEntryAtIndex(j);
973             addr_t next_base_addr = next_entry->GetRangeBase();
974             if (next_base_addr > curr_base_addr) {
975               addr_t size_to_next_symbol = next_base_addr - curr_base_addr;
976 
977               // Take the difference between this symbol and the next one as
978               // its size, if it is less than the size of the section.
979               if (sym_size == 0 || size_to_next_symbol < sym_size) {
980                 sym_size = size_to_next_symbol;
981               }
982               break;
983             }
984           }
985 
986           if (sym_size > 0) {
987             entry->SetByteSize(sym_size);
988             Symbol &symbol = m_symbols[entry->data];
989             symbol.SetByteSize(sym_size);
990             symbol.SetSizeIsSynthesized(true);
991           }
992         }
993       }
994 
995       // Sort again in case the range size changes the ordering
996       m_file_addr_to_index.Sort();
997     }
998   }
999 }
1000 
CalculateSymbolSizes()1001 void Symtab::CalculateSymbolSizes() {
1002   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1003   // Size computation happens inside InitAddressIndexes.
1004   InitAddressIndexes();
1005 }
1006 
FindSymbolAtFileAddress(addr_t file_addr)1007 Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) {
1008   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1009   if (!m_file_addr_to_index_computed)
1010     InitAddressIndexes();
1011 
1012   const FileRangeToIndexMap::Entry *entry =
1013       m_file_addr_to_index.FindEntryStartsAt(file_addr);
1014   if (entry) {
1015     Symbol *symbol = SymbolAtIndex(entry->data);
1016     if (symbol->GetFileAddress() == file_addr)
1017       return symbol;
1018   }
1019   return nullptr;
1020 }
1021 
FindSymbolContainingFileAddress(addr_t file_addr)1022 Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) {
1023   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1024 
1025   if (!m_file_addr_to_index_computed)
1026     InitAddressIndexes();
1027 
1028   const FileRangeToIndexMap::Entry *entry =
1029       m_file_addr_to_index.FindEntryThatContains(file_addr);
1030   if (entry) {
1031     Symbol *symbol = SymbolAtIndex(entry->data);
1032     if (symbol->ContainsFileAddress(file_addr))
1033       return symbol;
1034   }
1035   return nullptr;
1036 }
1037 
ForEachSymbolContainingFileAddress(addr_t file_addr,std::function<bool (Symbol *)> const & callback)1038 void Symtab::ForEachSymbolContainingFileAddress(
1039     addr_t file_addr, std::function<bool(Symbol *)> const &callback) {
1040   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1041 
1042   if (!m_file_addr_to_index_computed)
1043     InitAddressIndexes();
1044 
1045   std::vector<uint32_t> all_addr_indexes;
1046 
1047   // Get all symbols with file_addr
1048   const size_t addr_match_count =
1049       m_file_addr_to_index.FindEntryIndexesThatContain(file_addr,
1050                                                        all_addr_indexes);
1051 
1052   for (size_t i = 0; i < addr_match_count; ++i) {
1053     Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]);
1054     if (symbol->ContainsFileAddress(file_addr)) {
1055       if (!callback(symbol))
1056         break;
1057     }
1058   }
1059 }
1060 
SymbolIndicesToSymbolContextList(std::vector<uint32_t> & symbol_indexes,SymbolContextList & sc_list)1061 void Symtab::SymbolIndicesToSymbolContextList(
1062     std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) {
1063   // No need to protect this call using m_mutex all other method calls are
1064   // already thread safe.
1065 
1066   const bool merge_symbol_into_function = true;
1067   size_t num_indices = symbol_indexes.size();
1068   if (num_indices > 0) {
1069     SymbolContext sc;
1070     sc.module_sp = m_objfile->GetModule();
1071     for (size_t i = 0; i < num_indices; i++) {
1072       sc.symbol = SymbolAtIndex(symbol_indexes[i]);
1073       if (sc.symbol)
1074         sc_list.AppendIfUnique(sc, merge_symbol_into_function);
1075     }
1076   }
1077 }
1078 
FindFunctionSymbols(ConstString name,uint32_t name_type_mask,SymbolContextList & sc_list)1079 void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
1080                                  SymbolContextList &sc_list) {
1081   std::vector<uint32_t> symbol_indexes;
1082 
1083   // eFunctionNameTypeAuto should be pre-resolved by a call to
1084   // Module::LookupInfo::LookupInfo()
1085   assert((name_type_mask & eFunctionNameTypeAuto) == 0);
1086 
1087   if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) {
1088     std::vector<uint32_t> temp_symbol_indexes;
1089     FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes);
1090 
1091     unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1092     if (temp_symbol_indexes_size > 0) {
1093       std::lock_guard<std::recursive_mutex> guard(m_mutex);
1094       for (unsigned i = 0; i < temp_symbol_indexes_size; i++) {
1095         SymbolContext sym_ctx;
1096         sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]);
1097         if (sym_ctx.symbol) {
1098           switch (sym_ctx.symbol->GetType()) {
1099           case eSymbolTypeCode:
1100           case eSymbolTypeResolver:
1101           case eSymbolTypeReExported:
1102             symbol_indexes.push_back(temp_symbol_indexes[i]);
1103             break;
1104           default:
1105             break;
1106           }
1107         }
1108       }
1109     }
1110   }
1111 
1112   if (!m_name_indexes_computed)
1113     InitNameIndexes();
1114 
1115   for (lldb::FunctionNameType type :
1116        {lldb::eFunctionNameTypeBase, lldb::eFunctionNameTypeMethod,
1117         lldb::eFunctionNameTypeSelector}) {
1118     if (name_type_mask & type) {
1119       auto map = GetNameToSymbolIndexMap(type);
1120 
1121       const UniqueCStringMap<uint32_t>::Entry *match;
1122       for (match = map.FindFirstValueForName(name); match != nullptr;
1123            match = map.FindNextValueForName(match)) {
1124         symbol_indexes.push_back(match->value);
1125       }
1126     }
1127   }
1128 
1129   if (!symbol_indexes.empty()) {
1130     llvm::sort(symbol_indexes.begin(), symbol_indexes.end());
1131     symbol_indexes.erase(
1132         std::unique(symbol_indexes.begin(), symbol_indexes.end()),
1133         symbol_indexes.end());
1134     SymbolIndicesToSymbolContextList(symbol_indexes, sc_list);
1135   }
1136 }
1137 
GetParent(Symbol * child_symbol) const1138 const Symbol *Symtab::GetParent(Symbol *child_symbol) const {
1139   uint32_t child_idx = GetIndexForSymbol(child_symbol);
1140   if (child_idx != UINT32_MAX && child_idx > 0) {
1141     for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) {
1142       const Symbol *symbol = SymbolAtIndex(idx);
1143       const uint32_t sibling_idx = symbol->GetSiblingIndex();
1144       if (sibling_idx != UINT32_MAX && sibling_idx > child_idx)
1145         return symbol;
1146     }
1147   }
1148   return nullptr;
1149 }
1150