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