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