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