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