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