]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Symbol/Symtab.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / Symbol / Symtab.cpp
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 "lldb/Core/Module.h"
14 #include "lldb/Core/RegularExpression.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Symbol/ObjectFile.h"
19 #include "lldb/Symbol/Symbol.h"
20 #include "lldb/Symbol/SymbolContext.h"
21 #include "lldb/Symbol/Symtab.h"
22 #include "Plugins/Language/ObjC/ObjCLanguage.h"
23 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
24
25 using namespace lldb;
26 using namespace lldb_private;
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(),
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.empty() ? nullptr : &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     std::lock_guard<std::recursive_mutex> guard(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     std::lock_guard<std::recursive_mutex> guard(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->GetName().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     std::lock_guard<std::recursive_mutex> guard(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 = *(const user_id_t*) key;
214     const user_id_t symbol_uid = ((const 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     std::lock_guard<std::recursive_mutex> guard(m_mutex);
226
227     Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, 
228                                          &m_symbols[0], 
229                                          m_symbols.size(), 
230                                          sizeof(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                 if (symbol->ContainsLinkerAnnotations()) {
318                     // If the symbol has linker annotations, also add the version without the
319                     // annotations.
320                     entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
321                     m_name_to_index.Append (entry);
322                 }
323                 
324                 const SymbolType symbol_type = symbol->GetType();
325                 if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
326                 {
327                     if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
328                         (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
329                          entry.cstring[2] != 'G' && // avoid guard variables
330                          entry.cstring[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
331                     {
332                         CPlusPlusLanguage::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
333                         entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
334                         if (entry.cstring && entry.cstring[0])
335                         {
336                             // ConstString objects permanently store the string in the pool so calling
337                             // GetCString() on the value gets us a const char * that will never go away
338                             const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
339
340                             if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
341                             {
342                                 // The first character of the demangled basename is '~' which
343                                 // means we have a class destructor. We can use this information
344                                 // to help us know what is a class and what isn't.
345                                 if (class_contexts.find(const_context) == class_contexts.end())
346                                     class_contexts.insert(const_context);
347                                 m_method_to_index.Append (entry);
348                             }
349                             else
350                             {
351                                 if (const_context && const_context[0])
352                                 {
353                                     if (class_contexts.find(const_context) != class_contexts.end())
354                                     {
355                                         // The current decl context is in our "class_contexts" which means
356                                         // this is a method on a class
357                                         m_method_to_index.Append (entry);
358                                     }
359                                     else
360                                     {
361                                         // We don't know if this is a function basename or a method,
362                                         // so put it into a temporary collection so once we are done
363                                         // we can look in class_contexts to see if each entry is a class
364                                         // or just a function and will put any remaining items into
365                                         // m_method_to_index or m_basename_to_index as needed
366                                         mangled_name_to_index.Append (entry);
367                                         symbol_contexts[entry.value] = const_context;
368                                     }
369                                 }
370                                 else
371                                 {
372                                     // No context for this function so this has to be a basename
373                                     m_basename_to_index.Append(entry);
374                                 }
375                             }
376                         }
377                     }
378                 }
379             }
380             
381             entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
382             if (entry.cstring && entry.cstring[0]) {
383                 m_name_to_index.Append (entry);
384
385                 if (symbol->ContainsLinkerAnnotations()) {
386                     // If the symbol has linker annotations, also add the version without the
387                     // annotations.
388                     entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
389                     m_name_to_index.Append (entry);
390                 }
391             }
392                 
393             // If the demangled name turns out to be an ObjC name, and
394             // is a category name, add the version without categories to the index too.
395             ObjCLanguage::MethodName objc_method (entry.cstring, true);
396             if (objc_method.IsValid(true))
397             {
398                 entry.cstring = objc_method.GetSelector().GetCString();
399                 m_selector_to_index.Append (entry);
400                 
401                 ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true));
402                 if (objc_method_no_category)
403                 {
404                     entry.cstring = objc_method_no_category.GetCString();
405                     m_name_to_index.Append (entry);
406                 }
407             }
408                                                         
409         }
410         
411         size_t count;
412         if (!mangled_name_to_index.IsEmpty())
413         {
414             count = mangled_name_to_index.GetSize();
415             for (size_t i=0; i<count; ++i)
416             {
417                 if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
418                 {
419                     entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
420                     if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
421                     {
422                         m_method_to_index.Append (entry);
423                     }
424                     else
425                     {
426                         // If we got here, we have something that had a context (was inside a namespace or class)
427                         // yet we don't know if the entry
428                         m_method_to_index.Append (entry);
429                         m_basename_to_index.Append (entry);
430                     }
431                 }
432             }
433         }
434         m_name_to_index.Sort();
435         m_name_to_index.SizeToFit();
436         m_selector_to_index.Sort();
437         m_selector_to_index.SizeToFit();
438         m_basename_to_index.Sort();
439         m_basename_to_index.SizeToFit();
440         m_method_to_index.Sort();
441         m_method_to_index.SizeToFit();
442     
443 //        static StreamFile a ("/tmp/a.txt");
444 //
445 //        count = m_basename_to_index.GetSize();
446 //        if (count)
447 //        {
448 //            for (size_t i=0; i<count; ++i)
449 //            {
450 //                if (m_basename_to_index.GetValueAtIndex(i, entry.value))
451 //                    a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
452 //            }
453 //        }
454 //        count = m_method_to_index.GetSize();
455 //        if (count)
456 //        {
457 //            for (size_t i=0; i<count; ++i)
458 //            {
459 //                if (m_method_to_index.GetValueAtIndex(i, entry.value))
460 //                    a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
461 //            }
462 //        }
463     }
464 }
465
466 void
467 Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
468                                 bool add_demangled,
469                                 bool add_mangled,
470                                 NameToIndexMap &name_to_index_map) const
471 {
472     if (add_demangled || add_mangled)
473     {
474         Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
475         std::lock_guard<std::recursive_mutex> guard(m_mutex);
476
477         // Create the name index vector to be able to quickly search by name
478         NameToIndexMap::Entry entry;
479         const size_t num_indexes = indexes.size();
480         for (size_t i=0; i<num_indexes; ++i)
481         {
482             entry.value = indexes[i];
483             assert (i < m_symbols.size());
484             const Symbol *symbol = &m_symbols[entry.value];
485
486             const Mangled &mangled = symbol->GetMangled();
487             if (add_demangled)
488             {
489                 entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
490                 if (entry.cstring && entry.cstring[0])
491                     name_to_index_map.Append (entry);
492             }
493                 
494             if (add_mangled)
495             {
496                 entry.cstring = mangled.GetMangledName().GetCString();
497                 if (entry.cstring && entry.cstring[0])
498                     name_to_index_map.Append (entry);
499             }
500         }
501     }
502 }
503
504 uint32_t
505 Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
506 {
507     std::lock_guard<std::recursive_mutex> guard(m_mutex);
508
509     uint32_t prev_size = indexes.size();
510
511     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
512
513     for (uint32_t i = start_idx; i < count; ++i)
514     {
515         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
516             indexes.push_back(i);
517     }
518
519     return indexes.size() - prev_size;
520 }
521
522 uint32_t
523 Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
524 {
525     std::lock_guard<std::recursive_mutex> guard(m_mutex);
526
527     uint32_t prev_size = indexes.size();
528
529     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
530
531     for (uint32_t i = start_idx; i < count; ++i)
532     {
533         if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
534             indexes.push_back(i);
535     }
536
537     return indexes.size() - prev_size;
538 }
539
540 uint32_t
541 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
542 {
543     std::lock_guard<std::recursive_mutex> guard(m_mutex);
544
545     uint32_t prev_size = indexes.size();
546
547     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
548
549     for (uint32_t i = start_idx; i < count; ++i)
550     {
551         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
552         {
553             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
554                 indexes.push_back(i);
555         }
556     }
557
558     return indexes.size() - prev_size;
559 }
560
561
562 uint32_t
563 Symtab::GetIndexForSymbol (const Symbol *symbol) const
564 {
565     if (!m_symbols.empty())
566     {
567         const Symbol *first_symbol = &m_symbols[0];
568         if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
569             return symbol - first_symbol;
570     }
571     return UINT32_MAX;
572 }
573
574 struct SymbolSortInfo
575 {
576     const bool sort_by_load_addr;
577     const Symbol *symbols;
578 };
579
580 namespace {
581     struct SymbolIndexComparator {
582         const std::vector<Symbol>& symbols;
583         std::vector<lldb::addr_t>  &addr_cache;
584         
585         // Getting from the symbol to the Address to the File Address involves some work.
586         // Since there are potentially many symbols here, and we're using this for sorting so
587         // we're going to be computing the address many times, cache that in addr_cache.
588         // The array passed in has to be the same size as the symbols array passed into the
589         // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS.
590         // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort
591         // makes copies of the comparator it is initially passed in, and you end up spending
592         // huge amounts of time copying this array...
593         
594         SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a)  {
595             assert (symbols.size() == addr_cache.size());
596         }
597         bool operator()(uint32_t index_a, uint32_t index_b) {
598             addr_t value_a = addr_cache[index_a];
599             if (value_a == LLDB_INVALID_ADDRESS)
600             {
601                 value_a = symbols[index_a].GetAddressRef().GetFileAddress();
602                 addr_cache[index_a] = value_a;
603             }
604             
605             addr_t value_b = addr_cache[index_b];
606             if (value_b == LLDB_INVALID_ADDRESS)
607             {
608                 value_b = symbols[index_b].GetAddressRef().GetFileAddress();
609                 addr_cache[index_b] = value_b;
610             }
611             
612
613             if (value_a == value_b) {
614                 // The if the values are equal, use the original symbol user ID
615                 lldb::user_id_t uid_a = symbols[index_a].GetID();
616                 lldb::user_id_t uid_b = symbols[index_b].GetID();
617                 if (uid_a < uid_b)
618                     return true;
619                 if (uid_a > uid_b)
620                     return false;
621                 return false;
622             } else if (value_a < value_b)
623                 return true;
624         
625             return false;
626         }
627     };
628 }
629
630 void
631 Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
632 {
633     std::lock_guard<std::recursive_mutex> guard(m_mutex);
634
635     Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
636     // No need to sort if we have zero or one items...
637     if (indexes.size() <= 1)
638         return;
639
640     // Sort the indexes in place using std::stable_sort.
641     // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
642     // not correctness.  The indexes vector tends to be "close" to sorted, which the
643     // stable sort handles better.
644     
645     std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
646     
647     SymbolIndexComparator comparator(m_symbols, addr_cache);
648     std::stable_sort(indexes.begin(), indexes.end(), comparator);
649
650     // Remove any duplicates if requested
651     if (remove_duplicates)
652         std::unique(indexes.begin(), indexes.end());
653 }
654
655 uint32_t
656 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
657 {
658     std::lock_guard<std::recursive_mutex> guard(m_mutex);
659
660     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
661     if (symbol_name)
662     {
663         const char *symbol_cstr = symbol_name.GetCString();
664         if (!m_name_indexes_computed)
665             InitNameIndexes();
666
667         return m_name_to_index.GetValues (symbol_cstr, indexes);
668     }
669     return 0;
670 }
671
672 uint32_t
673 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
674 {
675     std::lock_guard<std::recursive_mutex> guard(m_mutex);
676
677     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
678     if (symbol_name)
679     {
680         const size_t old_size = indexes.size();
681         if (!m_name_indexes_computed)
682             InitNameIndexes();
683
684         const char *symbol_cstr = symbol_name.GetCString();
685         
686         std::vector<uint32_t> all_name_indexes;
687         const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
688         for (size_t i=0; i<name_match_count; ++i)
689         {
690             if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
691                 indexes.push_back (all_name_indexes[i]);
692         }
693         return indexes.size() - old_size;
694     }
695     return 0;
696 }
697
698 uint32_t
699 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
700 {
701     std::lock_guard<std::recursive_mutex> guard(m_mutex);
702
703     if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
704     {
705         std::vector<uint32_t>::iterator pos = indexes.begin();
706         while (pos != indexes.end())
707         {
708             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
709                 ++pos;
710             else
711                 pos = indexes.erase(pos);
712         }
713     }
714     return indexes.size();
715 }
716
717 uint32_t
718 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
719 {
720     std::lock_guard<std::recursive_mutex> guard(m_mutex);
721
722     if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
723     {
724         std::vector<uint32_t>::iterator pos = indexes.begin();
725         while (pos != indexes.end())
726         {
727             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
728                 ++pos;
729             else
730                 pos = indexes.erase(pos);
731         }
732     }
733     return indexes.size();
734 }
735
736
737 uint32_t
738 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
739 {
740     std::lock_guard<std::recursive_mutex> guard(m_mutex);
741
742     uint32_t prev_size = indexes.size();
743     uint32_t sym_end = m_symbols.size();
744
745     for (uint32_t i = 0; i < sym_end; i++)
746     {
747         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
748         {
749             const char *name = m_symbols[i].GetName().AsCString();
750             if (name)
751             {
752                 if (regexp.Execute (name))
753                     indexes.push_back(i);
754             }
755         }
756     }
757     return indexes.size() - prev_size;
758
759 }
760
761 uint32_t
762 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
763 {
764     std::lock_guard<std::recursive_mutex> guard(m_mutex);
765
766     uint32_t prev_size = indexes.size();
767     uint32_t sym_end = m_symbols.size();
768
769     for (uint32_t i = 0; i < sym_end; i++)
770     {
771         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
772         {
773             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
774                 continue;
775
776             const char *name = m_symbols[i].GetName().AsCString();
777             if (name)
778             {
779                 if (regexp.Execute (name))
780                     indexes.push_back(i);
781             }
782         }
783     }
784     return indexes.size() - prev_size;
785
786 }
787
788 Symbol *
789 Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
790 {
791     std::lock_guard<std::recursive_mutex> guard(m_mutex);
792
793     const size_t count = m_symbols.size();
794     for (size_t idx = start_idx; idx < count; ++idx)
795     {
796         if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
797         {
798             if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
799             {
800                 start_idx = idx;
801                 return &m_symbols[idx];
802             }
803         }
804     }
805     return nullptr;
806 }
807
808 size_t
809 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
810 {
811     std::lock_guard<std::recursive_mutex> guard(m_mutex);
812
813     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
814     // Initialize all of the lookup by name indexes before converting NAME
815     // to a uniqued string NAME_STR below.
816     if (!m_name_indexes_computed)
817         InitNameIndexes();
818
819     if (name)
820     {
821         // The string table did have a string that matched, but we need
822         // to check the symbols and match the symbol_type if any was given.
823         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
824     }
825     return symbol_indexes.size();
826 }
827
828 size_t
829 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
830 {
831     std::lock_guard<std::recursive_mutex> guard(m_mutex);
832
833     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
834     // Initialize all of the lookup by name indexes before converting NAME
835     // to a uniqued string NAME_STR below.
836     if (!m_name_indexes_computed)
837         InitNameIndexes();
838
839     if (name)
840     {
841         // The string table did have a string that matched, but we need
842         // to check the symbols and match the symbol_type if any was given.
843         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
844     }
845     return symbol_indexes.size();
846 }
847
848 size_t
849 Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
850 {
851     std::lock_guard<std::recursive_mutex> guard(m_mutex);
852
853     AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
854     return symbol_indexes.size();
855 }
856
857 Symbol *
858 Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
859 {
860     std::lock_guard<std::recursive_mutex> guard(m_mutex);
861
862     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
863     if (!m_name_indexes_computed)
864         InitNameIndexes();
865
866     if (name)
867     {
868         std::vector<uint32_t> matching_indexes;
869         // The string table did have a string that matched, but we need
870         // to check the symbols and match the symbol_type if any was given.
871         if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
872         {
873             std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
874             for (pos = matching_indexes.begin(); pos != end; ++pos)
875             {
876                 Symbol *symbol = SymbolAtIndex(*pos);
877
878                 if (symbol->Compare(name, symbol_type))
879                     return symbol;
880             }
881         }
882     }
883     return nullptr;
884 }
885
886 typedef struct
887 {
888     const Symtab *symtab;
889     const addr_t file_addr;
890     Symbol *match_symbol;
891     const uint32_t *match_index_ptr;
892     addr_t match_offset;
893 } SymbolSearchInfo;
894
895 // Add all the section file start address & size to the RangeVector,
896 // recusively adding any children sections.  
897 static void
898 AddSectionsToRangeMap (SectionList *sectlist, RangeVector<addr_t, addr_t> &section_ranges)
899 {
900     const int num_sections = sectlist->GetNumSections (0);
901     for (int i = 0; i < num_sections; i++)
902     {
903         SectionSP sect_sp = sectlist->GetSectionAtIndex (i);
904         if (sect_sp)
905         {
906             SectionList &child_sectlist = sect_sp->GetChildren();
907
908             // If this section has children, add the children to the RangeVector.
909             // Else add this section to the RangeVector.
910             if (child_sectlist.GetNumSections (0) > 0)
911             {
912                 AddSectionsToRangeMap (&child_sectlist, section_ranges);
913             }
914             else
915             {
916                 size_t size = sect_sp->GetByteSize();
917                 if (size > 0)
918                 {
919                     addr_t base_addr = sect_sp->GetFileAddress();
920                     RangeVector<addr_t, addr_t>::Entry entry;
921                     entry.SetRangeBase (base_addr);
922                     entry.SetByteSize (size);
923                     section_ranges.Append (entry);
924                 }
925             }
926         }
927     }
928 }
929
930 void
931 Symtab::InitAddressIndexes()
932 {
933     // Protected function, no need to lock mutex...
934     if (!m_file_addr_to_index_computed && !m_symbols.empty())
935     {
936         m_file_addr_to_index_computed = true;
937
938         FileRangeToIndexMap::Entry entry;
939         const_iterator begin = m_symbols.begin();
940         const_iterator end = m_symbols.end();
941         for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
942         {
943             if (pos->ValueIsAddress())
944             {
945                 entry.SetRangeBase(pos->GetAddressRef().GetFileAddress());
946                 entry.SetByteSize(pos->GetByteSize());
947                 entry.data = std::distance(begin, pos);
948                 m_file_addr_to_index.Append(entry);
949             }
950         }
951         const size_t num_entries = m_file_addr_to_index.GetSize();
952         if (num_entries > 0)
953         {
954             m_file_addr_to_index.Sort();
955
956             // Create a RangeVector with the start & size of all the sections for
957             // this objfile.  We'll need to check this for any FileRangeToIndexMap
958             // entries with an uninitialized size, which could potentially be a
959             // large number so reconstituting the weak pointer is busywork when it
960             // is invariant information.
961             SectionList *sectlist = m_objfile->GetSectionList();
962             RangeVector<addr_t, addr_t> section_ranges;
963             if (sectlist)
964             {
965                 AddSectionsToRangeMap (sectlist, section_ranges);
966                 section_ranges.Sort();
967             }
968
969             // Iterate through the FileRangeToIndexMap and fill in the size for any
970             // entries that didn't already have a size from the Symbol (e.g. if we
971             // have a plain linker symbol with an address only, instead of debug info
972             // where we get an address and a size and a type, etc.)
973             for (size_t i = 0; i < num_entries; i++)
974             {
975                 FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.GetMutableEntryAtIndex (i);
976                 if (entry->GetByteSize() == 0)
977                 {
978                     addr_t curr_base_addr = entry->GetRangeBase();
979                     const RangeVector<addr_t, addr_t>::Entry *containing_section =
980                                                               section_ranges.FindEntryThatContains (curr_base_addr);
981
982                     // Use the end of the section as the default max size of the symbol
983                     addr_t sym_size = 0;
984                     if (containing_section)
985                     {
986                         sym_size = containing_section->GetByteSize() - 
987                                         (entry->GetRangeBase() - containing_section->GetRangeBase());
988                     }
989                     
990                     for (size_t j = i; j < num_entries; j++)
991                     {
992                         FileRangeToIndexMap::Entry *next_entry = m_file_addr_to_index.GetMutableEntryAtIndex (j);
993                         addr_t next_base_addr = next_entry->GetRangeBase();
994                         if (next_base_addr > curr_base_addr)
995                         {
996                             addr_t size_to_next_symbol = next_base_addr - curr_base_addr;
997
998                             // Take the difference between this symbol and the next one as its size,
999                             // if it is less than the size of the section.
1000                             if (sym_size == 0 || size_to_next_symbol < sym_size)
1001                             {
1002                                 sym_size = size_to_next_symbol;
1003                             }
1004                             break;
1005                         }
1006                     }
1007
1008                     if (sym_size > 0)
1009                     {
1010                         entry->SetByteSize (sym_size);
1011                         Symbol &symbol = m_symbols[entry->data];
1012                         symbol.SetByteSize (sym_size);
1013                         symbol.SetSizeIsSynthesized (true);
1014                     }
1015                 }
1016             }
1017
1018             // Sort again in case the range size changes the ordering
1019             m_file_addr_to_index.Sort();
1020         }
1021     }
1022 }
1023
1024 void
1025 Symtab::CalculateSymbolSizes ()
1026 {
1027     std::lock_guard<std::recursive_mutex> guard(m_mutex);
1028
1029     if (!m_symbols.empty())
1030     {
1031         if (!m_file_addr_to_index_computed)
1032             InitAddressIndexes();
1033         
1034         const size_t num_entries = m_file_addr_to_index.GetSize();
1035
1036         for (size_t i = 0; i < num_entries; ++i)
1037         {
1038             // The entries in the m_file_addr_to_index have calculated the sizes already
1039             // so we will use this size if we need to.
1040             const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
1041             
1042             Symbol &symbol = m_symbols[entry.data];
1043
1044             // If the symbol size is already valid, no need to do anything
1045             if (symbol.GetByteSizeIsValid())
1046                 continue;
1047             
1048             const addr_t range_size = entry.GetByteSize();
1049             if (range_size > 0)
1050             {
1051                 symbol.SetByteSize(range_size);
1052                 symbol.SetSizeIsSynthesized(true);
1053             }
1054         }
1055     }
1056 }
1057
1058 Symbol *
1059 Symtab::FindSymbolAtFileAddress (addr_t file_addr)
1060 {
1061     std::lock_guard<std::recursive_mutex> guard(m_mutex);
1062     if (!m_file_addr_to_index_computed)
1063         InitAddressIndexes();
1064
1065     const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryStartsAt(file_addr);
1066     if (entry)
1067     {
1068         Symbol* symbol = SymbolAtIndex(entry->data);
1069         if (symbol->GetFileAddress() == file_addr)
1070             return symbol;
1071     }
1072     return nullptr;
1073 }
1074
1075 Symbol *
1076 Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
1077 {
1078     std::lock_guard<std::recursive_mutex> guard(m_mutex);
1079
1080     if (!m_file_addr_to_index_computed)
1081         InitAddressIndexes();
1082
1083     const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr);
1084     if (entry)
1085     {
1086         Symbol* symbol = SymbolAtIndex(entry->data);
1087         if (symbol->ContainsFileAddress(file_addr))
1088             return symbol;
1089     }
1090     return nullptr;
1091 }
1092
1093 void
1094 Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool(Symbol *)> const &callback)
1095 {
1096     std::lock_guard<std::recursive_mutex> guard(m_mutex);
1097
1098     if (!m_file_addr_to_index_computed)
1099         InitAddressIndexes();
1100
1101     std::vector<uint32_t> all_addr_indexes;
1102
1103     // Get all symbols with file_addr
1104     const size_t addr_match_count = m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, all_addr_indexes);
1105
1106     for (size_t i = 0; i < addr_match_count; ++i)
1107     {
1108         Symbol* symbol = SymbolAtIndex(all_addr_indexes[i]);
1109         if (symbol->ContainsFileAddress(file_addr))
1110         {
1111             if (!callback(symbol))
1112                 break;
1113         }
1114     }
1115 }
1116
1117 void
1118 Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
1119 {
1120     // No need to protect this call using m_mutex all other method calls are
1121     // already thread safe.
1122     
1123     const bool merge_symbol_into_function = true;
1124     size_t num_indices = symbol_indexes.size();
1125     if (num_indices > 0)
1126     {
1127         SymbolContext sc;
1128         sc.module_sp = m_objfile->GetModule();
1129         for (size_t i = 0; i < num_indices; i++)
1130         {
1131             sc.symbol = SymbolAtIndex (symbol_indexes[i]);
1132             if (sc.symbol)
1133                 sc_list.AppendIfUnique(sc, merge_symbol_into_function);
1134         }
1135     }
1136 }
1137
1138
1139 size_t
1140 Symtab::FindFunctionSymbols (const ConstString &name,
1141                              uint32_t name_type_mask,
1142                              SymbolContextList& sc_list)
1143 {
1144     size_t count = 0;
1145     std::vector<uint32_t> symbol_indexes;
1146     
1147     const char *name_cstr = name.GetCString();
1148     
1149     // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
1150     assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
1151
1152     if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
1153     {
1154         std::vector<uint32_t> temp_symbol_indexes;
1155         FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes);
1156
1157         unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1158         if (temp_symbol_indexes_size > 0)
1159         {
1160             std::lock_guard<std::recursive_mutex> guard(m_mutex);
1161             for (unsigned i = 0; i < temp_symbol_indexes_size; i++)
1162             {
1163                 SymbolContext sym_ctx;
1164                 sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]);
1165                 if (sym_ctx.symbol)
1166                 {
1167                     switch (sym_ctx.symbol->GetType())
1168                     {
1169                     case eSymbolTypeCode:
1170                     case eSymbolTypeResolver:
1171                     case eSymbolTypeReExported:
1172                         symbol_indexes.push_back(temp_symbol_indexes[i]);
1173                         break;
1174                     default:
1175                         break;
1176                     }
1177                 }
1178             }
1179         }
1180     }
1181     
1182     if (name_type_mask & eFunctionNameTypeBase)
1183     {
1184         // From mangled names we can't tell what is a basename and what
1185         // is a method name, so we just treat them the same
1186         if (!m_name_indexes_computed)
1187             InitNameIndexes();
1188
1189         if (!m_basename_to_index.IsEmpty())
1190         {
1191             const UniqueCStringMap<uint32_t>::Entry *match;
1192             for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
1193                  match != nullptr;
1194                  match = m_basename_to_index.FindNextValueForName(match))
1195             {
1196                 symbol_indexes.push_back(match->value);
1197             }
1198         }
1199     }
1200     
1201     if (name_type_mask & eFunctionNameTypeMethod)
1202     {
1203         if (!m_name_indexes_computed)
1204             InitNameIndexes();
1205         
1206         if (!m_method_to_index.IsEmpty())
1207         {
1208             const UniqueCStringMap<uint32_t>::Entry *match;
1209             for (match = m_method_to_index.FindFirstValueForName(name_cstr);
1210                  match != nullptr;
1211                  match = m_method_to_index.FindNextValueForName(match))
1212             {
1213                 symbol_indexes.push_back(match->value);
1214             }
1215         }
1216     }
1217
1218     if (name_type_mask & eFunctionNameTypeSelector)
1219     {
1220         if (!m_name_indexes_computed)
1221             InitNameIndexes();
1222
1223         if (!m_selector_to_index.IsEmpty())
1224         {
1225             const UniqueCStringMap<uint32_t>::Entry *match;
1226             for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
1227                  match != nullptr;
1228                  match = m_selector_to_index.FindNextValueForName(match))
1229             {
1230                 symbol_indexes.push_back(match->value);
1231             }
1232         }
1233     }
1234
1235     if (!symbol_indexes.empty())
1236     {
1237         std::sort(symbol_indexes.begin(), symbol_indexes.end());
1238         symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end());
1239         count = symbol_indexes.size();
1240         SymbolIndicesToSymbolContextList (symbol_indexes, sc_list);
1241     }
1242
1243     return count;
1244 }
1245
1246
1247 const Symbol *
1248 Symtab::GetParent (Symbol *child_symbol) const
1249 {
1250     uint32_t child_idx = GetIndexForSymbol(child_symbol);
1251     if (child_idx != UINT32_MAX && child_idx > 0)
1252     {
1253         for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx)
1254         {
1255             const Symbol *symbol = SymbolAtIndex (idx);
1256             const uint32_t sibling_idx = symbol->GetSiblingIndex();
1257             if (sibling_idx != UINT32_MAX && sibling_idx > child_idx)
1258                 return symbol;
1259         }
1260     }
1261     return NULL;
1262 }