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