10b57cec5SDimitry Andric //===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include <map>
100b57cec5SDimitry Andric #include <set>
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "Plugins/Language/ObjC/ObjCLanguage.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "lldb/Core/Module.h"
150b57cec5SDimitry Andric #include "lldb/Core/RichManglingContext.h"
160b57cec5SDimitry Andric #include "lldb/Core/Section.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
190b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
200b57cec5SDimitry Andric #include "lldb/Symbol/Symtab.h"
210b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace lldb;
280b57cec5SDimitry Andric using namespace lldb_private;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric Symtab::Symtab(ObjectFile *objfile)
31480093f4SDimitry Andric     : m_objfile(objfile), m_symbols(), m_file_addr_to_index(*this),
320b57cec5SDimitry Andric       m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false),
330b57cec5SDimitry Andric       m_name_indexes_computed(false) {}
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric Symtab::~Symtab() {}
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric void Symtab::Reserve(size_t count) {
380b57cec5SDimitry Andric   // Clients should grab the mutex from this symbol table and lock it manually
390b57cec5SDimitry Andric   // when calling this function to avoid performance issues.
400b57cec5SDimitry Andric   m_symbols.reserve(count);
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric Symbol *Symtab::Resize(size_t count) {
440b57cec5SDimitry Andric   // Clients should grab the mutex from this symbol table and lock it manually
450b57cec5SDimitry Andric   // when calling this function to avoid performance issues.
460b57cec5SDimitry Andric   m_symbols.resize(count);
470b57cec5SDimitry Andric   return m_symbols.empty() ? nullptr : &m_symbols[0];
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric uint32_t Symtab::AddSymbol(const Symbol &symbol) {
510b57cec5SDimitry Andric   // Clients should grab the mutex from this symbol table and lock it manually
520b57cec5SDimitry Andric   // when calling this function to avoid performance issues.
530b57cec5SDimitry Andric   uint32_t symbol_idx = m_symbols.size();
540b57cec5SDimitry Andric   m_name_to_index.Clear();
550b57cec5SDimitry Andric   m_file_addr_to_index.Clear();
560b57cec5SDimitry Andric   m_symbols.push_back(symbol);
570b57cec5SDimitry Andric   m_file_addr_to_index_computed = false;
580b57cec5SDimitry Andric   m_name_indexes_computed = false;
590b57cec5SDimitry Andric   return symbol_idx;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric size_t Symtab::GetNumSymbols() const {
630b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
640b57cec5SDimitry Andric   return m_symbols.size();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric void Symtab::SectionFileAddressesChanged() {
680b57cec5SDimitry Andric   m_name_to_index.Clear();
690b57cec5SDimitry Andric   m_file_addr_to_index_computed = false;
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
72480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order,
73480093f4SDimitry Andric                   Mangled::NamePreference name_preference) {
740b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
770b57cec5SDimitry Andric   s->Indent();
780b57cec5SDimitry Andric   const FileSpec &file_spec = m_objfile->GetFileSpec();
790b57cec5SDimitry Andric   const char *object_name = nullptr;
800b57cec5SDimitry Andric   if (m_objfile->GetModule())
810b57cec5SDimitry Andric     object_name = m_objfile->GetModule()->GetObjectName().GetCString();
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   if (file_spec)
840b57cec5SDimitry Andric     s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64,
850b57cec5SDimitry Andric               file_spec.GetPath().c_str(), object_name ? "(" : "",
860b57cec5SDimitry Andric               object_name ? object_name : "", object_name ? ")" : "",
870b57cec5SDimitry Andric               (uint64_t)m_symbols.size());
880b57cec5SDimitry Andric   else
890b57cec5SDimitry Andric     s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size());
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   if (!m_symbols.empty()) {
920b57cec5SDimitry Andric     switch (sort_order) {
930b57cec5SDimitry Andric     case eSortOrderNone: {
940b57cec5SDimitry Andric       s->PutCString(":\n");
950b57cec5SDimitry Andric       DumpSymbolHeader(s);
960b57cec5SDimitry Andric       const_iterator begin = m_symbols.begin();
970b57cec5SDimitry Andric       const_iterator end = m_symbols.end();
980b57cec5SDimitry Andric       for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
990b57cec5SDimitry Andric         s->Indent();
100480093f4SDimitry Andric         pos->Dump(s, target, std::distance(begin, pos), name_preference);
1010b57cec5SDimitry Andric       }
1020b57cec5SDimitry Andric     } break;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     case eSortOrderByName: {
1050b57cec5SDimitry Andric       // Although we maintain a lookup by exact name map, the table isn't
1060b57cec5SDimitry Andric       // sorted by name. So we must make the ordered symbol list up ourselves.
1070b57cec5SDimitry Andric       s->PutCString(" (sorted by name):\n");
1080b57cec5SDimitry Andric       DumpSymbolHeader(s);
109480093f4SDimitry Andric 
110480093f4SDimitry Andric       std::multimap<llvm::StringRef, const Symbol *> name_map;
1110b57cec5SDimitry Andric       for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
1120b57cec5SDimitry Andric            pos != end; ++pos) {
1130b57cec5SDimitry Andric         const char *name = pos->GetName().AsCString();
1140b57cec5SDimitry Andric         if (name && name[0])
1150b57cec5SDimitry Andric           name_map.insert(std::make_pair(name, &(*pos)));
1160b57cec5SDimitry Andric       }
1170b57cec5SDimitry Andric 
118480093f4SDimitry Andric       for (const auto &name_to_symbol : name_map) {
119480093f4SDimitry Andric         const Symbol *symbol = name_to_symbol.second;
1200b57cec5SDimitry Andric         s->Indent();
121480093f4SDimitry Andric         symbol->Dump(s, target, symbol - &m_symbols[0], name_preference);
1220b57cec5SDimitry Andric       }
1230b57cec5SDimitry Andric     } break;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     case eSortOrderByAddress:
1260b57cec5SDimitry Andric       s->PutCString(" (sorted by address):\n");
1270b57cec5SDimitry Andric       DumpSymbolHeader(s);
1280b57cec5SDimitry Andric       if (!m_file_addr_to_index_computed)
1290b57cec5SDimitry Andric         InitAddressIndexes();
1300b57cec5SDimitry Andric       const size_t num_entries = m_file_addr_to_index.GetSize();
1310b57cec5SDimitry Andric       for (size_t i = 0; i < num_entries; ++i) {
1320b57cec5SDimitry Andric         s->Indent();
1330b57cec5SDimitry Andric         const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
134480093f4SDimitry Andric         m_symbols[symbol_idx].Dump(s, target, symbol_idx, name_preference);
1350b57cec5SDimitry Andric       }
1360b57cec5SDimitry Andric       break;
1370b57cec5SDimitry Andric     }
1380b57cec5SDimitry Andric   } else {
1390b57cec5SDimitry Andric     s->PutCString("\n");
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
143480093f4SDimitry Andric void Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t> &indexes,
144480093f4SDimitry Andric                   Mangled::NamePreference name_preference) const {
1450b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   const size_t num_symbols = GetNumSymbols();
1480b57cec5SDimitry Andric   // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
1490b57cec5SDimitry Andric   s->Indent();
1500b57cec5SDimitry Andric   s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n",
1510b57cec5SDimitry Andric             (uint64_t)indexes.size(), (uint64_t)m_symbols.size());
1520b57cec5SDimitry Andric   s->IndentMore();
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   if (!indexes.empty()) {
1550b57cec5SDimitry Andric     std::vector<uint32_t>::const_iterator pos;
1560b57cec5SDimitry Andric     std::vector<uint32_t>::const_iterator end = indexes.end();
1570b57cec5SDimitry Andric     DumpSymbolHeader(s);
1580b57cec5SDimitry Andric     for (pos = indexes.begin(); pos != end; ++pos) {
1590b57cec5SDimitry Andric       size_t idx = *pos;
1600b57cec5SDimitry Andric       if (idx < num_symbols) {
1610b57cec5SDimitry Andric         s->Indent();
162480093f4SDimitry Andric         m_symbols[idx].Dump(s, target, idx, name_preference);
1630b57cec5SDimitry Andric       }
1640b57cec5SDimitry Andric     }
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric   s->IndentLess();
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric void Symtab::DumpSymbolHeader(Stream *s) {
1700b57cec5SDimitry Andric   s->Indent("               Debug symbol\n");
1710b57cec5SDimitry Andric   s->Indent("               |Synthetic symbol\n");
1720b57cec5SDimitry Andric   s->Indent("               ||Externally Visible\n");
1730b57cec5SDimitry Andric   s->Indent("               |||\n");
1740b57cec5SDimitry Andric   s->Indent("Index   UserID DSX Type            File Address/Value Load "
1750b57cec5SDimitry Andric             "Address       Size               Flags      Name\n");
1760b57cec5SDimitry Andric   s->Indent("------- ------ --- --------------- ------------------ "
1770b57cec5SDimitry Andric             "------------------ ------------------ ---------- "
1780b57cec5SDimitry Andric             "----------------------------------\n");
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric static int CompareSymbolID(const void *key, const void *p) {
1820b57cec5SDimitry Andric   const user_id_t match_uid = *(const user_id_t *)key;
1830b57cec5SDimitry Andric   const user_id_t symbol_uid = ((const Symbol *)p)->GetID();
1840b57cec5SDimitry Andric   if (match_uid < symbol_uid)
1850b57cec5SDimitry Andric     return -1;
1860b57cec5SDimitry Andric   if (match_uid > symbol_uid)
1870b57cec5SDimitry Andric     return 1;
1880b57cec5SDimitry Andric   return 0;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const {
1920b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   Symbol *symbol =
1950b57cec5SDimitry Andric       (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(),
1960b57cec5SDimitry Andric                           sizeof(m_symbols[0]), CompareSymbolID);
1970b57cec5SDimitry Andric   return symbol;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric Symbol *Symtab::SymbolAtIndex(size_t idx) {
2010b57cec5SDimitry Andric   // Clients should grab the mutex from this symbol table and lock it manually
2020b57cec5SDimitry Andric   // when calling this function to avoid performance issues.
2030b57cec5SDimitry Andric   if (idx < m_symbols.size())
2040b57cec5SDimitry Andric     return &m_symbols[idx];
2050b57cec5SDimitry Andric   return nullptr;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric const Symbol *Symtab::SymbolAtIndex(size_t idx) const {
2090b57cec5SDimitry Andric   // Clients should grab the mutex from this symbol table and lock it manually
2100b57cec5SDimitry Andric   // when calling this function to avoid performance issues.
2110b57cec5SDimitry Andric   if (idx < m_symbols.size())
2120b57cec5SDimitry Andric     return &m_symbols[idx];
2130b57cec5SDimitry Andric   return nullptr;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric static bool lldb_skip_name(llvm::StringRef mangled,
2170b57cec5SDimitry Andric                            Mangled::ManglingScheme scheme) {
2180b57cec5SDimitry Andric   switch (scheme) {
2190b57cec5SDimitry Andric   case Mangled::eManglingSchemeItanium: {
2200b57cec5SDimitry Andric     if (mangled.size() < 3 || !mangled.startswith("_Z"))
2210b57cec5SDimitry Andric       return true;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric     // Avoid the following types of symbols in the index.
2240b57cec5SDimitry Andric     switch (mangled[2]) {
2250b57cec5SDimitry Andric     case 'G': // guard variables
2260b57cec5SDimitry Andric     case 'T': // virtual tables, VTT structures, typeinfo structures + names
2270b57cec5SDimitry Andric     case 'Z': // named local entities (if we eventually handle
2280b57cec5SDimitry Andric               // eSymbolTypeData, we will want this back)
2290b57cec5SDimitry Andric       return true;
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric     default:
2320b57cec5SDimitry Andric       break;
2330b57cec5SDimitry Andric     }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric     // Include this name in the index.
2360b57cec5SDimitry Andric     return false;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   // No filters for this scheme yet. Include all names in indexing.
2400b57cec5SDimitry Andric   case Mangled::eManglingSchemeMSVC:
2410b57cec5SDimitry Andric     return false;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   // Don't try and demangle things we can't categorize.
2440b57cec5SDimitry Andric   case Mangled::eManglingSchemeNone:
2450b57cec5SDimitry Andric     return true;
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric   llvm_unreachable("unknown scheme!");
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric void Symtab::InitNameIndexes() {
2510b57cec5SDimitry Andric   // Protected function, no need to lock mutex...
2520b57cec5SDimitry Andric   if (!m_name_indexes_computed) {
2530b57cec5SDimitry Andric     m_name_indexes_computed = true;
2540b57cec5SDimitry Andric     static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
2550b57cec5SDimitry Andric     Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
2560b57cec5SDimitry Andric     // Create the name index vector to be able to quickly search by name
2570b57cec5SDimitry Andric     const size_t num_symbols = m_symbols.size();
2580b57cec5SDimitry Andric     m_name_to_index.Reserve(num_symbols);
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric     // The "const char *" in "class_contexts" and backlog::value_type::second
2610b57cec5SDimitry Andric     // must come from a ConstString::GetCString()
2620b57cec5SDimitry Andric     std::set<const char *> class_contexts;
2630b57cec5SDimitry Andric     std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog;
2640b57cec5SDimitry Andric     backlog.reserve(num_symbols / 2);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     // Instantiation of the demangler is expensive, so better use a single one
2670b57cec5SDimitry Andric     // for all entries during batch processing.
2680b57cec5SDimitry Andric     RichManglingContext rmc;
2690b57cec5SDimitry Andric     for (uint32_t value = 0; value < num_symbols; ++value) {
2700b57cec5SDimitry Andric       Symbol *symbol = &m_symbols[value];
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric       // Don't let trampolines get into the lookup by name map If we ever need
2730b57cec5SDimitry Andric       // the trampoline symbols to be searchable by name we can remove this and
2740b57cec5SDimitry Andric       // then possibly add a new bool to any of the Symtab functions that
2750b57cec5SDimitry Andric       // lookup symbols by name to indicate if they want trampolines.
2760b57cec5SDimitry Andric       if (symbol->IsTrampoline())
2770b57cec5SDimitry Andric         continue;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric       // If the symbol's name string matched a Mangled::ManglingScheme, it is
2800b57cec5SDimitry Andric       // stored in the mangled field.
2810b57cec5SDimitry Andric       Mangled &mangled = symbol->GetMangled();
2820b57cec5SDimitry Andric       if (ConstString name = mangled.GetMangledName()) {
2830b57cec5SDimitry Andric         m_name_to_index.Append(name, value);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric         if (symbol->ContainsLinkerAnnotations()) {
2860b57cec5SDimitry Andric           // If the symbol has linker annotations, also add the version without
2870b57cec5SDimitry Andric           // the annotations.
2880b57cec5SDimitry Andric           ConstString stripped = ConstString(
2890b57cec5SDimitry Andric               m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
2900b57cec5SDimitry Andric           m_name_to_index.Append(stripped, value);
2910b57cec5SDimitry Andric         }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric         const SymbolType type = symbol->GetType();
2940b57cec5SDimitry Andric         if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
2950b57cec5SDimitry Andric           if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name))
2960b57cec5SDimitry Andric             RegisterMangledNameEntry(value, class_contexts, backlog, rmc);
2970b57cec5SDimitry Andric         }
2980b57cec5SDimitry Andric       }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       // Symbol name strings that didn't match a Mangled::ManglingScheme, are
3010b57cec5SDimitry Andric       // stored in the demangled field.
3020b57cec5SDimitry Andric       if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage())) {
3030b57cec5SDimitry Andric         m_name_to_index.Append(name, value);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric         if (symbol->ContainsLinkerAnnotations()) {
3060b57cec5SDimitry Andric           // If the symbol has linker annotations, also add the version without
3070b57cec5SDimitry Andric           // the annotations.
3080b57cec5SDimitry Andric           name = ConstString(
3090b57cec5SDimitry Andric               m_objfile->StripLinkerSymbolAnnotations(name.GetStringRef()));
3100b57cec5SDimitry Andric           m_name_to_index.Append(name, value);
3110b57cec5SDimitry Andric         }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric         // If the demangled name turns out to be an ObjC name, and is a category
3140b57cec5SDimitry Andric         // name, add the version without categories to the index too.
3150b57cec5SDimitry Andric         ObjCLanguage::MethodName objc_method(name.GetStringRef(), true);
3160b57cec5SDimitry Andric         if (objc_method.IsValid(true)) {
3170b57cec5SDimitry Andric           m_selector_to_index.Append(objc_method.GetSelector(), value);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric           if (ConstString objc_method_no_category =
3200b57cec5SDimitry Andric                   objc_method.GetFullNameWithoutCategory(true))
3210b57cec5SDimitry Andric             m_name_to_index.Append(objc_method_no_category, value);
3220b57cec5SDimitry Andric         }
3230b57cec5SDimitry Andric       }
3240b57cec5SDimitry Andric     }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric     for (const auto &record : backlog) {
3270b57cec5SDimitry Andric       RegisterBacklogEntry(record.first, record.second, class_contexts);
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric     m_name_to_index.Sort();
3310b57cec5SDimitry Andric     m_name_to_index.SizeToFit();
3320b57cec5SDimitry Andric     m_selector_to_index.Sort();
3330b57cec5SDimitry Andric     m_selector_to_index.SizeToFit();
3340b57cec5SDimitry Andric     m_basename_to_index.Sort();
3350b57cec5SDimitry Andric     m_basename_to_index.SizeToFit();
3360b57cec5SDimitry Andric     m_method_to_index.Sort();
3370b57cec5SDimitry Andric     m_method_to_index.SizeToFit();
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric void Symtab::RegisterMangledNameEntry(
3420b57cec5SDimitry Andric     uint32_t value, std::set<const char *> &class_contexts,
3430b57cec5SDimitry Andric     std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
3440b57cec5SDimitry Andric     RichManglingContext &rmc) {
3450b57cec5SDimitry Andric   // Only register functions that have a base name.
3460b57cec5SDimitry Andric   rmc.ParseFunctionBaseName();
3470b57cec5SDimitry Andric   llvm::StringRef base_name = rmc.GetBufferRef();
3480b57cec5SDimitry Andric   if (base_name.empty())
3490b57cec5SDimitry Andric     return;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   // The base name will be our entry's name.
3520b57cec5SDimitry Andric   NameToIndexMap::Entry entry(ConstString(base_name), value);
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   rmc.ParseFunctionDeclContextName();
3550b57cec5SDimitry Andric   llvm::StringRef decl_context = rmc.GetBufferRef();
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   // Register functions with no context.
3580b57cec5SDimitry Andric   if (decl_context.empty()) {
3590b57cec5SDimitry Andric     // This has to be a basename
3600b57cec5SDimitry Andric     m_basename_to_index.Append(entry);
3610b57cec5SDimitry Andric     // If there is no context (no namespaces or class scopes that come before
3620b57cec5SDimitry Andric     // the function name) then this also could be a fullname.
3630b57cec5SDimitry Andric     m_name_to_index.Append(entry);
3640b57cec5SDimitry Andric     return;
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   // Make sure we have a pool-string pointer and see if we already know the
3680b57cec5SDimitry Andric   // context name.
3690b57cec5SDimitry Andric   const char *decl_context_ccstr = ConstString(decl_context).GetCString();
3700b57cec5SDimitry Andric   auto it = class_contexts.find(decl_context_ccstr);
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   // Register constructors and destructors. They are methods and create
3730b57cec5SDimitry Andric   // declaration contexts.
3740b57cec5SDimitry Andric   if (rmc.IsCtorOrDtor()) {
3750b57cec5SDimitry Andric     m_method_to_index.Append(entry);
3760b57cec5SDimitry Andric     if (it == class_contexts.end())
3770b57cec5SDimitry Andric       class_contexts.insert(it, decl_context_ccstr);
3780b57cec5SDimitry Andric     return;
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // Register regular methods with a known declaration context.
3820b57cec5SDimitry Andric   if (it != class_contexts.end()) {
3830b57cec5SDimitry Andric     m_method_to_index.Append(entry);
3840b57cec5SDimitry Andric     return;
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   // Regular methods in unknown declaration contexts are put to the backlog. We
3880b57cec5SDimitry Andric   // will revisit them once we processed all remaining symbols.
3890b57cec5SDimitry Andric   backlog.push_back(std::make_pair(entry, decl_context_ccstr));
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric void Symtab::RegisterBacklogEntry(
3930b57cec5SDimitry Andric     const NameToIndexMap::Entry &entry, const char *decl_context,
3940b57cec5SDimitry Andric     const std::set<const char *> &class_contexts) {
3950b57cec5SDimitry Andric   auto it = class_contexts.find(decl_context);
3960b57cec5SDimitry Andric   if (it != class_contexts.end()) {
3970b57cec5SDimitry Andric     m_method_to_index.Append(entry);
3980b57cec5SDimitry Andric   } else {
3990b57cec5SDimitry Andric     // If we got here, we have something that had a context (was inside
4000b57cec5SDimitry Andric     // a namespace or class) yet we don't know the entry
4010b57cec5SDimitry Andric     m_method_to_index.Append(entry);
4020b57cec5SDimitry Andric     m_basename_to_index.Append(entry);
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric void Symtab::PreloadSymbols() {
4070b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
4080b57cec5SDimitry Andric   InitNameIndexes();
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes,
4120b57cec5SDimitry Andric                                     bool add_demangled, bool add_mangled,
4130b57cec5SDimitry Andric                                     NameToIndexMap &name_to_index_map) const {
4140b57cec5SDimitry Andric   if (add_demangled || add_mangled) {
4150b57cec5SDimitry Andric     static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
4160b57cec5SDimitry Andric     Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
4170b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_mutex);
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric     // Create the name index vector to be able to quickly search by name
4200b57cec5SDimitry Andric     const size_t num_indexes = indexes.size();
4210b57cec5SDimitry Andric     for (size_t i = 0; i < num_indexes; ++i) {
4220b57cec5SDimitry Andric       uint32_t value = indexes[i];
4230b57cec5SDimitry Andric       assert(i < m_symbols.size());
4240b57cec5SDimitry Andric       const Symbol *symbol = &m_symbols[value];
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric       const Mangled &mangled = symbol->GetMangled();
4270b57cec5SDimitry Andric       if (add_demangled) {
4280b57cec5SDimitry Andric         if (ConstString name = mangled.GetDemangledName(symbol->GetLanguage()))
4290b57cec5SDimitry Andric           name_to_index_map.Append(name, value);
4300b57cec5SDimitry Andric       }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric       if (add_mangled) {
4330b57cec5SDimitry Andric         if (ConstString name = mangled.GetMangledName())
4340b57cec5SDimitry Andric           name_to_index_map.Append(name, value);
4350b57cec5SDimitry Andric       }
4360b57cec5SDimitry Andric     }
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type,
4410b57cec5SDimitry Andric                                              std::vector<uint32_t> &indexes,
4420b57cec5SDimitry Andric                                              uint32_t start_idx,
4430b57cec5SDimitry Andric                                              uint32_t end_index) const {
4440b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   uint32_t prev_size = indexes.size();
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   for (uint32_t i = start_idx; i < count; ++i) {
4510b57cec5SDimitry Andric     if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
4520b57cec5SDimitry Andric       indexes.push_back(i);
4530b57cec5SDimitry Andric   }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric   return indexes.size() - prev_size;
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue(
4590b57cec5SDimitry Andric     SymbolType symbol_type, uint32_t flags_value,
4600b57cec5SDimitry Andric     std::vector<uint32_t> &indexes, uint32_t start_idx,
4610b57cec5SDimitry Andric     uint32_t end_index) const {
4620b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   uint32_t prev_size = indexes.size();
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   for (uint32_t i = start_idx; i < count; ++i) {
4690b57cec5SDimitry Andric     if ((symbol_type == eSymbolTypeAny ||
4700b57cec5SDimitry Andric          m_symbols[i].GetType() == symbol_type) &&
4710b57cec5SDimitry Andric         m_symbols[i].GetFlags() == flags_value)
4720b57cec5SDimitry Andric       indexes.push_back(i);
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   return indexes.size() - prev_size;
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type,
4790b57cec5SDimitry Andric                                              Debug symbol_debug_type,
4800b57cec5SDimitry Andric                                              Visibility symbol_visibility,
4810b57cec5SDimitry Andric                                              std::vector<uint32_t> &indexes,
4820b57cec5SDimitry Andric                                              uint32_t start_idx,
4830b57cec5SDimitry Andric                                              uint32_t end_index) const {
4840b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   uint32_t prev_size = indexes.size();
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   for (uint32_t i = start_idx; i < count; ++i) {
4910b57cec5SDimitry Andric     if (symbol_type == eSymbolTypeAny ||
4920b57cec5SDimitry Andric         m_symbols[i].GetType() == symbol_type) {
4930b57cec5SDimitry Andric       if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
4940b57cec5SDimitry Andric         indexes.push_back(i);
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   return indexes.size() - prev_size;
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const {
5020b57cec5SDimitry Andric   if (!m_symbols.empty()) {
5030b57cec5SDimitry Andric     const Symbol *first_symbol = &m_symbols[0];
5040b57cec5SDimitry Andric     if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
5050b57cec5SDimitry Andric       return symbol - first_symbol;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric   return UINT32_MAX;
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric struct SymbolSortInfo {
5110b57cec5SDimitry Andric   const bool sort_by_load_addr;
5120b57cec5SDimitry Andric   const Symbol *symbols;
5130b57cec5SDimitry Andric };
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric namespace {
5160b57cec5SDimitry Andric struct SymbolIndexComparator {
5170b57cec5SDimitry Andric   const std::vector<Symbol> &symbols;
5180b57cec5SDimitry Andric   std::vector<lldb::addr_t> &addr_cache;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   // Getting from the symbol to the Address to the File Address involves some
5210b57cec5SDimitry Andric   // work. Since there are potentially many symbols here, and we're using this
5220b57cec5SDimitry Andric   // for sorting so we're going to be computing the address many times, cache
5230b57cec5SDimitry Andric   // that in addr_cache. The array passed in has to be the same size as the
5240b57cec5SDimitry Andric   // symbols array passed into the member variable symbols, and should be
5250b57cec5SDimitry Andric   // initialized with LLDB_INVALID_ADDRESS.
5260b57cec5SDimitry Andric   // NOTE: You have to make addr_cache externally and pass it in because
5270b57cec5SDimitry Andric   // std::stable_sort
5280b57cec5SDimitry Andric   // makes copies of the comparator it is initially passed in, and you end up
5290b57cec5SDimitry Andric   // spending huge amounts of time copying this array...
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   SymbolIndexComparator(const std::vector<Symbol> &s,
5320b57cec5SDimitry Andric                         std::vector<lldb::addr_t> &a)
5330b57cec5SDimitry Andric       : symbols(s), addr_cache(a) {
5340b57cec5SDimitry Andric     assert(symbols.size() == addr_cache.size());
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric   bool operator()(uint32_t index_a, uint32_t index_b) {
5370b57cec5SDimitry Andric     addr_t value_a = addr_cache[index_a];
5380b57cec5SDimitry Andric     if (value_a == LLDB_INVALID_ADDRESS) {
5390b57cec5SDimitry Andric       value_a = symbols[index_a].GetAddressRef().GetFileAddress();
5400b57cec5SDimitry Andric       addr_cache[index_a] = value_a;
5410b57cec5SDimitry Andric     }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric     addr_t value_b = addr_cache[index_b];
5440b57cec5SDimitry Andric     if (value_b == LLDB_INVALID_ADDRESS) {
5450b57cec5SDimitry Andric       value_b = symbols[index_b].GetAddressRef().GetFileAddress();
5460b57cec5SDimitry Andric       addr_cache[index_b] = value_b;
5470b57cec5SDimitry Andric     }
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric     if (value_a == value_b) {
5500b57cec5SDimitry Andric       // The if the values are equal, use the original symbol user ID
5510b57cec5SDimitry Andric       lldb::user_id_t uid_a = symbols[index_a].GetID();
5520b57cec5SDimitry Andric       lldb::user_id_t uid_b = symbols[index_b].GetID();
5530b57cec5SDimitry Andric       if (uid_a < uid_b)
5540b57cec5SDimitry Andric         return true;
5550b57cec5SDimitry Andric       if (uid_a > uid_b)
5560b57cec5SDimitry Andric         return false;
5570b57cec5SDimitry Andric       return false;
5580b57cec5SDimitry Andric     } else if (value_a < value_b)
5590b57cec5SDimitry Andric       return true;
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     return false;
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric };
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
5670b57cec5SDimitry Andric                                       bool remove_duplicates) const {
5680b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
5710b57cec5SDimitry Andric   Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
5720b57cec5SDimitry Andric   // No need to sort if we have zero or one items...
5730b57cec5SDimitry Andric   if (indexes.size() <= 1)
5740b57cec5SDimitry Andric     return;
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   // Sort the indexes in place using std::stable_sort.
5770b57cec5SDimitry Andric   // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly
5780b57cec5SDimitry Andric   // for performance, not correctness.  The indexes vector tends to be "close"
5790b57cec5SDimitry Andric   // to sorted, which the stable sort handles better.
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   SymbolIndexComparator comparator(m_symbols, addr_cache);
5840b57cec5SDimitry Andric   std::stable_sort(indexes.begin(), indexes.end(), comparator);
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   // Remove any duplicates if requested
5870b57cec5SDimitry Andric   if (remove_duplicates) {
5880b57cec5SDimitry Andric     auto last = std::unique(indexes.begin(), indexes.end());
5890b57cec5SDimitry Andric     indexes.erase(last, indexes.end());
5900b57cec5SDimitry Andric   }
5910b57cec5SDimitry Andric }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
5940b57cec5SDimitry Andric                                              std::vector<uint32_t> &indexes) {
5950b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
5980b57cec5SDimitry Andric   Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
5990b57cec5SDimitry Andric   if (symbol_name) {
6000b57cec5SDimitry Andric     if (!m_name_indexes_computed)
6010b57cec5SDimitry Andric       InitNameIndexes();
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric     return m_name_to_index.GetValues(symbol_name, indexes);
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric   return 0;
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithName(ConstString symbol_name,
6090b57cec5SDimitry Andric                                              Debug symbol_debug_type,
6100b57cec5SDimitry Andric                                              Visibility symbol_visibility,
6110b57cec5SDimitry Andric                                              std::vector<uint32_t> &indexes) {
6120b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
6150b57cec5SDimitry Andric   Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
6160b57cec5SDimitry Andric   if (symbol_name) {
6170b57cec5SDimitry Andric     const size_t old_size = indexes.size();
6180b57cec5SDimitry Andric     if (!m_name_indexes_computed)
6190b57cec5SDimitry Andric       InitNameIndexes();
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric     std::vector<uint32_t> all_name_indexes;
6220b57cec5SDimitry Andric     const size_t name_match_count =
6230b57cec5SDimitry Andric         m_name_to_index.GetValues(symbol_name, all_name_indexes);
6240b57cec5SDimitry Andric     for (size_t i = 0; i < name_match_count; ++i) {
6250b57cec5SDimitry Andric       if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type,
6260b57cec5SDimitry Andric                              symbol_visibility))
6270b57cec5SDimitry Andric         indexes.push_back(all_name_indexes[i]);
6280b57cec5SDimitry Andric     }
6290b57cec5SDimitry Andric     return indexes.size() - old_size;
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric   return 0;
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric uint32_t
6350b57cec5SDimitry Andric Symtab::AppendSymbolIndexesWithNameAndType(ConstString symbol_name,
6360b57cec5SDimitry Andric                                            SymbolType symbol_type,
6370b57cec5SDimitry Andric                                            std::vector<uint32_t> &indexes) {
6380b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) {
6410b57cec5SDimitry Andric     std::vector<uint32_t>::iterator pos = indexes.begin();
6420b57cec5SDimitry Andric     while (pos != indexes.end()) {
6430b57cec5SDimitry Andric       if (symbol_type == eSymbolTypeAny ||
6440b57cec5SDimitry Andric           m_symbols[*pos].GetType() == symbol_type)
6450b57cec5SDimitry Andric         ++pos;
6460b57cec5SDimitry Andric       else
6470b57cec5SDimitry Andric         pos = indexes.erase(pos);
6480b57cec5SDimitry Andric     }
6490b57cec5SDimitry Andric   }
6500b57cec5SDimitry Andric   return indexes.size();
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesWithNameAndType(
6540b57cec5SDimitry Andric     ConstString symbol_name, SymbolType symbol_type,
6550b57cec5SDimitry Andric     Debug symbol_debug_type, Visibility symbol_visibility,
6560b57cec5SDimitry Andric     std::vector<uint32_t> &indexes) {
6570b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type,
6600b57cec5SDimitry Andric                                   symbol_visibility, indexes) > 0) {
6610b57cec5SDimitry Andric     std::vector<uint32_t>::iterator pos = indexes.begin();
6620b57cec5SDimitry Andric     while (pos != indexes.end()) {
6630b57cec5SDimitry Andric       if (symbol_type == eSymbolTypeAny ||
6640b57cec5SDimitry Andric           m_symbols[*pos].GetType() == symbol_type)
6650b57cec5SDimitry Andric         ++pos;
6660b57cec5SDimitry Andric       else
6670b57cec5SDimitry Andric         pos = indexes.erase(pos);
6680b57cec5SDimitry Andric     }
6690b57cec5SDimitry Andric   }
6700b57cec5SDimitry Andric   return indexes.size();
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
6740b57cec5SDimitry Andric     const RegularExpression &regexp, SymbolType symbol_type,
6750b57cec5SDimitry Andric     std::vector<uint32_t> &indexes) {
6760b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   uint32_t prev_size = indexes.size();
6790b57cec5SDimitry Andric   uint32_t sym_end = m_symbols.size();
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   for (uint32_t i = 0; i < sym_end; i++) {
6820b57cec5SDimitry Andric     if (symbol_type == eSymbolTypeAny ||
6830b57cec5SDimitry Andric         m_symbols[i].GetType() == symbol_type) {
6840b57cec5SDimitry Andric       const char *name = m_symbols[i].GetName().AsCString();
6850b57cec5SDimitry Andric       if (name) {
6860b57cec5SDimitry Andric         if (regexp.Execute(name))
6870b57cec5SDimitry Andric           indexes.push_back(i);
6880b57cec5SDimitry Andric       }
6890b57cec5SDimitry Andric     }
6900b57cec5SDimitry Andric   }
6910b57cec5SDimitry Andric   return indexes.size() - prev_size;
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
6950b57cec5SDimitry Andric     const RegularExpression &regexp, SymbolType symbol_type,
6960b57cec5SDimitry Andric     Debug symbol_debug_type, Visibility symbol_visibility,
6970b57cec5SDimitry Andric     std::vector<uint32_t> &indexes) {
6980b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   uint32_t prev_size = indexes.size();
7010b57cec5SDimitry Andric   uint32_t sym_end = m_symbols.size();
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   for (uint32_t i = 0; i < sym_end; i++) {
7040b57cec5SDimitry Andric     if (symbol_type == eSymbolTypeAny ||
7050b57cec5SDimitry Andric         m_symbols[i].GetType() == symbol_type) {
7060b57cec5SDimitry Andric       if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
7070b57cec5SDimitry Andric         continue;
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric       const char *name = m_symbols[i].GetName().AsCString();
7100b57cec5SDimitry Andric       if (name) {
7110b57cec5SDimitry Andric         if (regexp.Execute(name))
7120b57cec5SDimitry Andric           indexes.push_back(i);
7130b57cec5SDimitry Andric       }
7140b57cec5SDimitry Andric     }
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric   return indexes.size() - prev_size;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type,
7200b57cec5SDimitry Andric                                    Debug symbol_debug_type,
7210b57cec5SDimitry Andric                                    Visibility symbol_visibility,
7220b57cec5SDimitry Andric                                    uint32_t &start_idx) {
7230b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric   const size_t count = m_symbols.size();
7260b57cec5SDimitry Andric   for (size_t idx = start_idx; idx < count; ++idx) {
7270b57cec5SDimitry Andric     if (symbol_type == eSymbolTypeAny ||
7280b57cec5SDimitry Andric         m_symbols[idx].GetType() == symbol_type) {
7290b57cec5SDimitry Andric       if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) {
7300b57cec5SDimitry Andric         start_idx = idx;
7310b57cec5SDimitry Andric         return &m_symbols[idx];
7320b57cec5SDimitry Andric       }
7330b57cec5SDimitry Andric     }
7340b57cec5SDimitry Andric   }
7350b57cec5SDimitry Andric   return nullptr;
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
7389dba64beSDimitry Andric void
7390b57cec5SDimitry Andric Symtab::FindAllSymbolsWithNameAndType(ConstString name,
7400b57cec5SDimitry Andric                                       SymbolType symbol_type,
7410b57cec5SDimitry Andric                                       std::vector<uint32_t> &symbol_indexes) {
7420b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
7450b57cec5SDimitry Andric   Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
7460b57cec5SDimitry Andric   // Initialize all of the lookup by name indexes before converting NAME to a
7470b57cec5SDimitry Andric   // uniqued string NAME_STR below.
7480b57cec5SDimitry Andric   if (!m_name_indexes_computed)
7490b57cec5SDimitry Andric     InitNameIndexes();
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   if (name) {
7520b57cec5SDimitry Andric     // The string table did have a string that matched, but we need to check
7530b57cec5SDimitry Andric     // the symbols and match the symbol_type if any was given.
7540b57cec5SDimitry Andric     AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
7550b57cec5SDimitry Andric   }
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric 
7589dba64beSDimitry Andric void Symtab::FindAllSymbolsWithNameAndType(
7590b57cec5SDimitry Andric     ConstString name, SymbolType symbol_type, Debug symbol_debug_type,
7600b57cec5SDimitry Andric     Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) {
7610b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
7640b57cec5SDimitry Andric   Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
7650b57cec5SDimitry Andric   // Initialize all of the lookup by name indexes before converting NAME to a
7660b57cec5SDimitry Andric   // uniqued string NAME_STR below.
7670b57cec5SDimitry Andric   if (!m_name_indexes_computed)
7680b57cec5SDimitry Andric     InitNameIndexes();
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   if (name) {
7710b57cec5SDimitry Andric     // The string table did have a string that matched, but we need to check
7720b57cec5SDimitry Andric     // the symbols and match the symbol_type if any was given.
7730b57cec5SDimitry Andric     AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
7740b57cec5SDimitry Andric                                        symbol_visibility, symbol_indexes);
7750b57cec5SDimitry Andric   }
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
7789dba64beSDimitry Andric void Symtab::FindAllSymbolsMatchingRexExAndType(
7790b57cec5SDimitry Andric     const RegularExpression &regex, SymbolType symbol_type,
7800b57cec5SDimitry Andric     Debug symbol_debug_type, Visibility symbol_visibility,
7810b57cec5SDimitry Andric     std::vector<uint32_t> &symbol_indexes) {
7820b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type,
7850b57cec5SDimitry Andric                                           symbol_visibility, symbol_indexes);
7860b57cec5SDimitry Andric }
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name,
7890b57cec5SDimitry Andric                                                SymbolType symbol_type,
7900b57cec5SDimitry Andric                                                Debug symbol_debug_type,
7910b57cec5SDimitry Andric                                                Visibility symbol_visibility) {
7920b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
7950b57cec5SDimitry Andric   Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
7960b57cec5SDimitry Andric   if (!m_name_indexes_computed)
7970b57cec5SDimitry Andric     InitNameIndexes();
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   if (name) {
8000b57cec5SDimitry Andric     std::vector<uint32_t> matching_indexes;
8010b57cec5SDimitry Andric     // The string table did have a string that matched, but we need to check
8020b57cec5SDimitry Andric     // the symbols and match the symbol_type if any was given.
8030b57cec5SDimitry Andric     if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
8040b57cec5SDimitry Andric                                            symbol_visibility,
8050b57cec5SDimitry Andric                                            matching_indexes)) {
8060b57cec5SDimitry Andric       std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
8070b57cec5SDimitry Andric       for (pos = matching_indexes.begin(); pos != end; ++pos) {
8080b57cec5SDimitry Andric         Symbol *symbol = SymbolAtIndex(*pos);
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric         if (symbol->Compare(name, symbol_type))
8110b57cec5SDimitry Andric           return symbol;
8120b57cec5SDimitry Andric       }
8130b57cec5SDimitry Andric     }
8140b57cec5SDimitry Andric   }
8150b57cec5SDimitry Andric   return nullptr;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric typedef struct {
8190b57cec5SDimitry Andric   const Symtab *symtab;
8200b57cec5SDimitry Andric   const addr_t file_addr;
8210b57cec5SDimitry Andric   Symbol *match_symbol;
8220b57cec5SDimitry Andric   const uint32_t *match_index_ptr;
8230b57cec5SDimitry Andric   addr_t match_offset;
8240b57cec5SDimitry Andric } SymbolSearchInfo;
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric // Add all the section file start address & size to the RangeVector, recusively
8270b57cec5SDimitry Andric // adding any children sections.
8280b57cec5SDimitry Andric static void AddSectionsToRangeMap(SectionList *sectlist,
8290b57cec5SDimitry Andric                                   RangeVector<addr_t, addr_t> &section_ranges) {
8300b57cec5SDimitry Andric   const int num_sections = sectlist->GetNumSections(0);
8310b57cec5SDimitry Andric   for (int i = 0; i < num_sections; i++) {
8320b57cec5SDimitry Andric     SectionSP sect_sp = sectlist->GetSectionAtIndex(i);
8330b57cec5SDimitry Andric     if (sect_sp) {
8340b57cec5SDimitry Andric       SectionList &child_sectlist = sect_sp->GetChildren();
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric       // If this section has children, add the children to the RangeVector.
8370b57cec5SDimitry Andric       // Else add this section to the RangeVector.
8380b57cec5SDimitry Andric       if (child_sectlist.GetNumSections(0) > 0) {
8390b57cec5SDimitry Andric         AddSectionsToRangeMap(&child_sectlist, section_ranges);
8400b57cec5SDimitry Andric       } else {
8410b57cec5SDimitry Andric         size_t size = sect_sp->GetByteSize();
8420b57cec5SDimitry Andric         if (size > 0) {
8430b57cec5SDimitry Andric           addr_t base_addr = sect_sp->GetFileAddress();
8440b57cec5SDimitry Andric           RangeVector<addr_t, addr_t>::Entry entry;
8450b57cec5SDimitry Andric           entry.SetRangeBase(base_addr);
8460b57cec5SDimitry Andric           entry.SetByteSize(size);
8470b57cec5SDimitry Andric           section_ranges.Append(entry);
8480b57cec5SDimitry Andric         }
8490b57cec5SDimitry Andric       }
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric   }
8520b57cec5SDimitry Andric }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric void Symtab::InitAddressIndexes() {
8550b57cec5SDimitry Andric   // Protected function, no need to lock mutex...
8560b57cec5SDimitry Andric   if (!m_file_addr_to_index_computed && !m_symbols.empty()) {
8570b57cec5SDimitry Andric     m_file_addr_to_index_computed = true;
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric     FileRangeToIndexMap::Entry entry;
8600b57cec5SDimitry Andric     const_iterator begin = m_symbols.begin();
8610b57cec5SDimitry Andric     const_iterator end = m_symbols.end();
8620b57cec5SDimitry Andric     for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
8630b57cec5SDimitry Andric       if (pos->ValueIsAddress()) {
8640b57cec5SDimitry Andric         entry.SetRangeBase(pos->GetAddressRef().GetFileAddress());
8650b57cec5SDimitry Andric         entry.SetByteSize(pos->GetByteSize());
8660b57cec5SDimitry Andric         entry.data = std::distance(begin, pos);
8670b57cec5SDimitry Andric         m_file_addr_to_index.Append(entry);
8680b57cec5SDimitry Andric       }
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric     const size_t num_entries = m_file_addr_to_index.GetSize();
8710b57cec5SDimitry Andric     if (num_entries > 0) {
8720b57cec5SDimitry Andric       m_file_addr_to_index.Sort();
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric       // Create a RangeVector with the start & size of all the sections for
8750b57cec5SDimitry Andric       // this objfile.  We'll need to check this for any FileRangeToIndexMap
8760b57cec5SDimitry Andric       // entries with an uninitialized size, which could potentially be a large
8770b57cec5SDimitry Andric       // number so reconstituting the weak pointer is busywork when it is
8780b57cec5SDimitry Andric       // invariant information.
8790b57cec5SDimitry Andric       SectionList *sectlist = m_objfile->GetSectionList();
8800b57cec5SDimitry Andric       RangeVector<addr_t, addr_t> section_ranges;
8810b57cec5SDimitry Andric       if (sectlist) {
8820b57cec5SDimitry Andric         AddSectionsToRangeMap(sectlist, section_ranges);
8830b57cec5SDimitry Andric         section_ranges.Sort();
8840b57cec5SDimitry Andric       }
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric       // Iterate through the FileRangeToIndexMap and fill in the size for any
8870b57cec5SDimitry Andric       // entries that didn't already have a size from the Symbol (e.g. if we
8880b57cec5SDimitry Andric       // have a plain linker symbol with an address only, instead of debug info
8890b57cec5SDimitry Andric       // where we get an address and a size and a type, etc.)
8900b57cec5SDimitry Andric       for (size_t i = 0; i < num_entries; i++) {
8910b57cec5SDimitry Andric         FileRangeToIndexMap::Entry *entry =
8920b57cec5SDimitry Andric             m_file_addr_to_index.GetMutableEntryAtIndex(i);
893c14a5a88SDimitry Andric         if (entry->GetByteSize() == 0) {
8940b57cec5SDimitry Andric           addr_t curr_base_addr = entry->GetRangeBase();
8950b57cec5SDimitry Andric           const RangeVector<addr_t, addr_t>::Entry *containing_section =
8960b57cec5SDimitry Andric               section_ranges.FindEntryThatContains(curr_base_addr);
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric           // Use the end of the section as the default max size of the symbol
8990b57cec5SDimitry Andric           addr_t sym_size = 0;
9000b57cec5SDimitry Andric           if (containing_section) {
9010b57cec5SDimitry Andric             sym_size =
9020b57cec5SDimitry Andric                 containing_section->GetByteSize() -
9030b57cec5SDimitry Andric                 (entry->GetRangeBase() - containing_section->GetRangeBase());
9040b57cec5SDimitry Andric           }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric           for (size_t j = i; j < num_entries; j++) {
9070b57cec5SDimitry Andric             FileRangeToIndexMap::Entry *next_entry =
9080b57cec5SDimitry Andric                 m_file_addr_to_index.GetMutableEntryAtIndex(j);
9090b57cec5SDimitry Andric             addr_t next_base_addr = next_entry->GetRangeBase();
9100b57cec5SDimitry Andric             if (next_base_addr > curr_base_addr) {
9110b57cec5SDimitry Andric               addr_t size_to_next_symbol = next_base_addr - curr_base_addr;
9120b57cec5SDimitry Andric 
9130b57cec5SDimitry Andric               // Take the difference between this symbol and the next one as
9140b57cec5SDimitry Andric               // its size, if it is less than the size of the section.
9150b57cec5SDimitry Andric               if (sym_size == 0 || size_to_next_symbol < sym_size) {
9160b57cec5SDimitry Andric                 sym_size = size_to_next_symbol;
9170b57cec5SDimitry Andric               }
9180b57cec5SDimitry Andric               break;
9190b57cec5SDimitry Andric             }
9200b57cec5SDimitry Andric           }
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric           if (sym_size > 0) {
9230b57cec5SDimitry Andric             entry->SetByteSize(sym_size);
9240b57cec5SDimitry Andric             Symbol &symbol = m_symbols[entry->data];
9250b57cec5SDimitry Andric             symbol.SetByteSize(sym_size);
9260b57cec5SDimitry Andric             symbol.SetSizeIsSynthesized(true);
9270b57cec5SDimitry Andric           }
9280b57cec5SDimitry Andric         }
9290b57cec5SDimitry Andric       }
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric       // Sort again in case the range size changes the ordering
9320b57cec5SDimitry Andric       m_file_addr_to_index.Sort();
9330b57cec5SDimitry Andric     }
9340b57cec5SDimitry Andric   }
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric void Symtab::CalculateSymbolSizes() {
9380b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9390b57cec5SDimitry Andric   // Size computation happens inside InitAddressIndexes.
9400b57cec5SDimitry Andric   InitAddressIndexes();
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) {
9440b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9450b57cec5SDimitry Andric   if (!m_file_addr_to_index_computed)
9460b57cec5SDimitry Andric     InitAddressIndexes();
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   const FileRangeToIndexMap::Entry *entry =
9490b57cec5SDimitry Andric       m_file_addr_to_index.FindEntryStartsAt(file_addr);
9500b57cec5SDimitry Andric   if (entry) {
9510b57cec5SDimitry Andric     Symbol *symbol = SymbolAtIndex(entry->data);
9520b57cec5SDimitry Andric     if (symbol->GetFileAddress() == file_addr)
9530b57cec5SDimitry Andric       return symbol;
9540b57cec5SDimitry Andric   }
9550b57cec5SDimitry Andric   return nullptr;
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) {
9590b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   if (!m_file_addr_to_index_computed)
9620b57cec5SDimitry Andric     InitAddressIndexes();
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   const FileRangeToIndexMap::Entry *entry =
9650b57cec5SDimitry Andric       m_file_addr_to_index.FindEntryThatContains(file_addr);
9660b57cec5SDimitry Andric   if (entry) {
9670b57cec5SDimitry Andric     Symbol *symbol = SymbolAtIndex(entry->data);
9680b57cec5SDimitry Andric     if (symbol->ContainsFileAddress(file_addr))
9690b57cec5SDimitry Andric       return symbol;
9700b57cec5SDimitry Andric   }
9710b57cec5SDimitry Andric   return nullptr;
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric void Symtab::ForEachSymbolContainingFileAddress(
9750b57cec5SDimitry Andric     addr_t file_addr, std::function<bool(Symbol *)> const &callback) {
9760b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   if (!m_file_addr_to_index_computed)
9790b57cec5SDimitry Andric     InitAddressIndexes();
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   std::vector<uint32_t> all_addr_indexes;
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   // Get all symbols with file_addr
9840b57cec5SDimitry Andric   const size_t addr_match_count =
9850b57cec5SDimitry Andric       m_file_addr_to_index.FindEntryIndexesThatContain(file_addr,
9860b57cec5SDimitry Andric                                                        all_addr_indexes);
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   for (size_t i = 0; i < addr_match_count; ++i) {
9890b57cec5SDimitry Andric     Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]);
9900b57cec5SDimitry Andric     if (symbol->ContainsFileAddress(file_addr)) {
9910b57cec5SDimitry Andric       if (!callback(symbol))
9920b57cec5SDimitry Andric         break;
9930b57cec5SDimitry Andric     }
9940b57cec5SDimitry Andric   }
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric void Symtab::SymbolIndicesToSymbolContextList(
9980b57cec5SDimitry Andric     std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) {
9990b57cec5SDimitry Andric   // No need to protect this call using m_mutex all other method calls are
10000b57cec5SDimitry Andric   // already thread safe.
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   const bool merge_symbol_into_function = true;
10030b57cec5SDimitry Andric   size_t num_indices = symbol_indexes.size();
10040b57cec5SDimitry Andric   if (num_indices > 0) {
10050b57cec5SDimitry Andric     SymbolContext sc;
10060b57cec5SDimitry Andric     sc.module_sp = m_objfile->GetModule();
10070b57cec5SDimitry Andric     for (size_t i = 0; i < num_indices; i++) {
10080b57cec5SDimitry Andric       sc.symbol = SymbolAtIndex(symbol_indexes[i]);
10090b57cec5SDimitry Andric       if (sc.symbol)
10100b57cec5SDimitry Andric         sc_list.AppendIfUnique(sc, merge_symbol_into_function);
10110b57cec5SDimitry Andric     }
10120b57cec5SDimitry Andric   }
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
10159dba64beSDimitry Andric void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask,
10160b57cec5SDimitry Andric                                  SymbolContextList &sc_list) {
10170b57cec5SDimitry Andric   std::vector<uint32_t> symbol_indexes;
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   // eFunctionNameTypeAuto should be pre-resolved by a call to
10200b57cec5SDimitry Andric   // Module::LookupInfo::LookupInfo()
10210b57cec5SDimitry Andric   assert((name_type_mask & eFunctionNameTypeAuto) == 0);
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) {
10240b57cec5SDimitry Andric     std::vector<uint32_t> temp_symbol_indexes;
10250b57cec5SDimitry Andric     FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes);
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric     unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
10280b57cec5SDimitry Andric     if (temp_symbol_indexes_size > 0) {
10290b57cec5SDimitry Andric       std::lock_guard<std::recursive_mutex> guard(m_mutex);
10300b57cec5SDimitry Andric       for (unsigned i = 0; i < temp_symbol_indexes_size; i++) {
10310b57cec5SDimitry Andric         SymbolContext sym_ctx;
10320b57cec5SDimitry Andric         sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]);
10330b57cec5SDimitry Andric         if (sym_ctx.symbol) {
10340b57cec5SDimitry Andric           switch (sym_ctx.symbol->GetType()) {
10350b57cec5SDimitry Andric           case eSymbolTypeCode:
10360b57cec5SDimitry Andric           case eSymbolTypeResolver:
10370b57cec5SDimitry Andric           case eSymbolTypeReExported:
10380b57cec5SDimitry Andric             symbol_indexes.push_back(temp_symbol_indexes[i]);
10390b57cec5SDimitry Andric             break;
10400b57cec5SDimitry Andric           default:
10410b57cec5SDimitry Andric             break;
10420b57cec5SDimitry Andric           }
10430b57cec5SDimitry Andric         }
10440b57cec5SDimitry Andric       }
10450b57cec5SDimitry Andric     }
10460b57cec5SDimitry Andric   }
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric   if (name_type_mask & eFunctionNameTypeBase) {
10490b57cec5SDimitry Andric     // From mangled names we can't tell what is a basename and what is a method
10500b57cec5SDimitry Andric     // name, so we just treat them the same
10510b57cec5SDimitry Andric     if (!m_name_indexes_computed)
10520b57cec5SDimitry Andric       InitNameIndexes();
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric     if (!m_basename_to_index.IsEmpty()) {
10550b57cec5SDimitry Andric       const UniqueCStringMap<uint32_t>::Entry *match;
10560b57cec5SDimitry Andric       for (match = m_basename_to_index.FindFirstValueForName(name);
10570b57cec5SDimitry Andric            match != nullptr;
10580b57cec5SDimitry Andric            match = m_basename_to_index.FindNextValueForName(match)) {
10590b57cec5SDimitry Andric         symbol_indexes.push_back(match->value);
10600b57cec5SDimitry Andric       }
10610b57cec5SDimitry Andric     }
10620b57cec5SDimitry Andric   }
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   if (name_type_mask & eFunctionNameTypeMethod) {
10650b57cec5SDimitry Andric     if (!m_name_indexes_computed)
10660b57cec5SDimitry Andric       InitNameIndexes();
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric     if (!m_method_to_index.IsEmpty()) {
10690b57cec5SDimitry Andric       const UniqueCStringMap<uint32_t>::Entry *match;
10700b57cec5SDimitry Andric       for (match = m_method_to_index.FindFirstValueForName(name);
10710b57cec5SDimitry Andric            match != nullptr;
10720b57cec5SDimitry Andric            match = m_method_to_index.FindNextValueForName(match)) {
10730b57cec5SDimitry Andric         symbol_indexes.push_back(match->value);
10740b57cec5SDimitry Andric       }
10750b57cec5SDimitry Andric     }
10760b57cec5SDimitry Andric   }
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   if (name_type_mask & eFunctionNameTypeSelector) {
10790b57cec5SDimitry Andric     if (!m_name_indexes_computed)
10800b57cec5SDimitry Andric       InitNameIndexes();
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric     if (!m_selector_to_index.IsEmpty()) {
10830b57cec5SDimitry Andric       const UniqueCStringMap<uint32_t>::Entry *match;
10840b57cec5SDimitry Andric       for (match = m_selector_to_index.FindFirstValueForName(name);
10850b57cec5SDimitry Andric            match != nullptr;
10860b57cec5SDimitry Andric            match = m_selector_to_index.FindNextValueForName(match)) {
10870b57cec5SDimitry Andric         symbol_indexes.push_back(match->value);
10880b57cec5SDimitry Andric       }
10890b57cec5SDimitry Andric     }
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   if (!symbol_indexes.empty()) {
10930b57cec5SDimitry Andric     llvm::sort(symbol_indexes.begin(), symbol_indexes.end());
10940b57cec5SDimitry Andric     symbol_indexes.erase(
10950b57cec5SDimitry Andric         std::unique(symbol_indexes.begin(), symbol_indexes.end()),
10960b57cec5SDimitry Andric         symbol_indexes.end());
10970b57cec5SDimitry Andric     SymbolIndicesToSymbolContextList(symbol_indexes, sc_list);
10980b57cec5SDimitry Andric   }
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric const Symbol *Symtab::GetParent(Symbol *child_symbol) const {
11020b57cec5SDimitry Andric   uint32_t child_idx = GetIndexForSymbol(child_symbol);
11030b57cec5SDimitry Andric   if (child_idx != UINT32_MAX && child_idx > 0) {
11040b57cec5SDimitry Andric     for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) {
11050b57cec5SDimitry Andric       const Symbol *symbol = SymbolAtIndex(idx);
11060b57cec5SDimitry Andric       const uint32_t sibling_idx = symbol->GetSiblingIndex();
11070b57cec5SDimitry Andric       if (sibling_idx != UINT32_MAX && sibling_idx > child_idx)
11080b57cec5SDimitry Andric         return symbol;
11090b57cec5SDimitry Andric     }
11100b57cec5SDimitry Andric   }
11110b57cec5SDimitry Andric   return nullptr;
11120b57cec5SDimitry Andric }
1113