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         SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
444         bool operator()(uint32_t index_a, uint32_t index_b) {
445             addr_t value_a;
446             addr_t value_b;
447             if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
448                 value_a = symbols[index_a].GetValue ().GetOffset();
449                 value_b = symbols[index_b].GetValue ().GetOffset();
450             } else {
451                 value_a = symbols[index_a].GetValue ().GetFileAddress();
452                 value_b = symbols[index_b].GetValue ().GetFileAddress();
453             }
454 
455             if (value_a == value_b) {
456                 // The if the values are equal, use the original symbol user ID
457                 lldb::user_id_t uid_a = symbols[index_a].GetID();
458                 lldb::user_id_t uid_b = symbols[index_b].GetID();
459                 if (uid_a < uid_b)
460                     return true;
461                 if (uid_a > uid_b)
462                     return false;
463                 return false;
464             } else if (value_a < value_b)
465                 return true;
466 
467             return false;
468         }
469     };
470 }
471 
472 void
473 Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
474 {
475     Mutex::Locker locker (m_mutex);
476 
477     Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
478     // No need to sort if we have zero or one items...
479     if (indexes.size() <= 1)
480         return;
481 
482     // Sort the indexes in place using std::stable_sort.
483     // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
484     // not correctness.  The indexes vector tends to be "close" to sorted, which the
485     // stable sort handles better.
486     std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
487 
488     // Remove any duplicates if requested
489     if (remove_duplicates)
490         std::unique(indexes.begin(), indexes.end());
491 }
492 
493 uint32_t
494 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
495 {
496     Mutex::Locker locker (m_mutex);
497 
498     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
499     if (symbol_name)
500     {
501         const char *symbol_cstr = symbol_name.GetCString();
502         if (!m_name_indexes_computed)
503             InitNameIndexes();
504 
505         return m_name_to_index.GetValues (symbol_cstr, indexes);
506     }
507     return 0;
508 }
509 
510 uint32_t
511 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
512 {
513     Mutex::Locker locker (m_mutex);
514 
515     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
516     if (symbol_name)
517     {
518         const size_t old_size = indexes.size();
519         if (!m_name_indexes_computed)
520             InitNameIndexes();
521 
522         const char *symbol_cstr = symbol_name.GetCString();
523 
524         std::vector<uint32_t> all_name_indexes;
525         const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
526         for (size_t i=0; i<name_match_count; ++i)
527         {
528             if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
529                 indexes.push_back (all_name_indexes[i]);
530         }
531         return indexes.size() - old_size;
532     }
533     return 0;
534 }
535 
536 uint32_t
537 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
538 {
539     Mutex::Locker locker (m_mutex);
540 
541     if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
542     {
543         std::vector<uint32_t>::iterator pos = indexes.begin();
544         while (pos != indexes.end())
545         {
546             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
547                 ++pos;
548             else
549                 indexes.erase(pos);
550         }
551     }
552     return indexes.size();
553 }
554 
555 uint32_t
556 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
557 {
558     Mutex::Locker locker (m_mutex);
559 
560     if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
561     {
562         std::vector<uint32_t>::iterator pos = indexes.begin();
563         while (pos != indexes.end())
564         {
565             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
566                 ++pos;
567             else
568                 indexes.erase(pos);
569         }
570     }
571     return indexes.size();
572 }
573 
574 
575 uint32_t
576 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
577 {
578     Mutex::Locker locker (m_mutex);
579 
580     uint32_t prev_size = indexes.size();
581     uint32_t sym_end = m_symbols.size();
582 
583     for (int i = 0; i < sym_end; i++)
584     {
585         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
586         {
587             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
588             if (name)
589             {
590                 if (regexp.Execute (name))
591                     indexes.push_back(i);
592             }
593         }
594     }
595     return indexes.size() - prev_size;
596 
597 }
598 
599 uint32_t
600 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
601 {
602     Mutex::Locker locker (m_mutex);
603 
604     uint32_t prev_size = indexes.size();
605     uint32_t sym_end = m_symbols.size();
606 
607     for (int i = 0; i < sym_end; i++)
608     {
609         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
610         {
611             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
612                 continue;
613 
614             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
615             if (name)
616             {
617                 if (regexp.Execute (name))
618                     indexes.push_back(i);
619             }
620         }
621     }
622     return indexes.size() - prev_size;
623 
624 }
625 
626 Symbol *
627 Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
628 {
629     Mutex::Locker locker (m_mutex);
630 
631     const size_t count = m_symbols.size();
632     for (uint32_t idx = start_idx; idx < count; ++idx)
633     {
634         if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
635         {
636             if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
637             {
638                 start_idx = idx;
639                 return &m_symbols[idx];
640             }
641         }
642     }
643     return NULL;
644 }
645 
646 size_t
647 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
648 {
649     Mutex::Locker locker (m_mutex);
650 
651     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
652     // Initialize all of the lookup by name indexes before converting NAME
653     // to a uniqued string NAME_STR below.
654     if (!m_name_indexes_computed)
655         InitNameIndexes();
656 
657     if (name)
658     {
659         // The string table did have a string that matched, but we need
660         // to check the symbols and match the symbol_type if any was given.
661         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
662     }
663     return symbol_indexes.size();
664 }
665 
666 size_t
667 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
668 {
669     Mutex::Locker locker (m_mutex);
670 
671     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
672     // Initialize all of the lookup by name indexes before converting NAME
673     // to a uniqued string NAME_STR below.
674     if (!m_name_indexes_computed)
675         InitNameIndexes();
676 
677     if (name)
678     {
679         // The string table did have a string that matched, but we need
680         // to check the symbols and match the symbol_type if any was given.
681         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
682     }
683     return symbol_indexes.size();
684 }
685 
686 size_t
687 Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
688 {
689     Mutex::Locker locker (m_mutex);
690 
691     AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
692     return symbol_indexes.size();
693 }
694 
695 Symbol *
696 Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
697 {
698     Mutex::Locker locker (m_mutex);
699 
700     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
701     if (!m_name_indexes_computed)
702         InitNameIndexes();
703 
704     if (name)
705     {
706         std::vector<uint32_t> matching_indexes;
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         if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
710         {
711             std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
712             for (pos = matching_indexes.begin(); pos != end; ++pos)
713             {
714                 Symbol *symbol = SymbolAtIndex(*pos);
715 
716                 if (symbol->Compare(name, symbol_type))
717                     return symbol;
718             }
719         }
720     }
721     return NULL;
722 }
723 
724 typedef struct
725 {
726     const Symtab *symtab;
727     const addr_t file_addr;
728     Symbol *match_symbol;
729     const uint32_t *match_index_ptr;
730     addr_t match_offset;
731 } SymbolSearchInfo;
732 
733 static int
734 SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
735 {
736     const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
737     if (curr_symbol == NULL)
738         return -1;
739 
740     const addr_t info_file_addr = info->file_addr;
741 
742     // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
743     // range if the symbol has a section!
744     const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
745     if (curr_range)
746     {
747         const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
748         if (info_file_addr < curr_file_addr)
749             return -1;
750         if (info_file_addr > curr_file_addr)
751             return +1;
752         info->match_symbol = const_cast<Symbol *>(curr_symbol);
753         info->match_index_ptr = index_ptr;
754         return 0;
755     }
756 
757     return -1;
758 }
759 
760 static int
761 SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
762 {
763     const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
764     if (symbol == NULL)
765         return -1;
766 
767     const addr_t info_file_addr = info->file_addr;
768     const AddressRange *curr_range = symbol->GetAddressRangePtr();
769     if (curr_range)
770     {
771         const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
772         if (info_file_addr < curr_file_addr)
773             return -1;
774 
775         // Since we are finding the closest symbol that is greater than or equal
776         // to 'info->file_addr' we set the symbol here. This will get set
777         // multiple times, but after the search is done it will contain the best
778         // symbol match
779         info->match_symbol = const_cast<Symbol *>(symbol);
780         info->match_index_ptr = index_ptr;
781         info->match_offset = info_file_addr - curr_file_addr;
782 
783         if (info_file_addr > curr_file_addr)
784             return +1;
785         return 0;
786     }
787     return -1;
788 }
789 
790 static SymbolSearchInfo
791 FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
792 {
793     SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
794     ::bsearch (&info,
795                indexes,
796                num_indexes,
797                sizeof(uint32_t),
798                (ComparisonFunction)SymbolWithClosestFileAddress);
799     return info;
800 }
801 
802 
803 void
804 Symtab::InitAddressIndexes()
805 {
806     // Protected function, no need to lock mutex...
807     if (!m_addr_indexes_computed && !m_symbols.empty())
808     {
809         m_addr_indexes_computed = true;
810 #if 0
811         // The old was to add only code, trampoline or data symbols...
812         AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
813         AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
814         AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
815 #else
816         // The new way adds all symbols with valid addresses that are section
817         // offset.
818         const_iterator begin = m_symbols.begin();
819         const_iterator end = m_symbols.end();
820         for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
821         {
822             if (pos->GetAddressRangePtr())
823                 m_addr_indexes.push_back (std::distance(begin, pos));
824         }
825 #endif
826         SortSymbolIndexesByValue (m_addr_indexes, false);
827         m_addr_indexes.push_back (UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
828     }
829 }
830 
831 size_t
832 Symtab::CalculateSymbolSize (Symbol *symbol)
833 {
834     Mutex::Locker locker (m_mutex);
835 
836     if (m_symbols.empty())
837         return 0;
838 
839     // Make sure this symbol is from this symbol table...
840     if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
841         return 0;
842 
843     // See if this symbol already has a byte size?
844     size_t byte_size = symbol->GetByteSize();
845 
846     if (byte_size)
847     {
848         // It does, just return it
849         return byte_size;
850     }
851 
852     // Else if this is an address based symbol, figure out the delta between
853     // it and the next address based symbol
854     if (symbol->GetAddressRangePtr())
855     {
856         if (!m_addr_indexes_computed)
857             InitAddressIndexes();
858         const size_t num_addr_indexes = m_addr_indexes.size();
859         SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
860         if (info.match_index_ptr != NULL)
861         {
862             const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
863             // We can figure out the address range of all symbols except the
864             // last one by taking the delta between the current symbol and
865             // the next symbol
866 
867             for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
868                  addr_index < num_addr_indexes;
869                  ++addr_index)
870             {
871                 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
872                 if (next_symbol == NULL)
873                     break;
874 
875                 assert (next_symbol->GetAddressRangePtr());
876                 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
877                 if (next_file_addr > curr_file_addr)
878                 {
879                     byte_size = next_file_addr - curr_file_addr;
880                     symbol->GetAddressRangePtr()->SetByteSize(byte_size);
881                     symbol->SetSizeIsSynthesized(true);
882                     break;
883                 }
884             }
885         }
886     }
887     return byte_size;
888 }
889 
890 Symbol *
891 Symtab::FindSymbolWithFileAddress (addr_t file_addr)
892 {
893     Mutex::Locker locker (m_mutex);
894 
895     if (!m_addr_indexes_computed)
896         InitAddressIndexes();
897 
898     SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
899 
900     uint32_t* match = (uint32_t*)::bsearch (&info,
901                                             &m_addr_indexes[0],
902                                             m_addr_indexes.size(),
903                                             sizeof(uint32_t),
904                                             (ComparisonFunction)SymbolWithFileAddress);
905     if (match)
906         return SymbolAtIndex (*match);
907     return NULL;
908 }
909 
910 
911 Symbol *
912 Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
913 {
914     Mutex::Locker locker (m_mutex);
915 
916     SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
917 
918     ::bsearch (&info,
919                indexes,
920                num_indexes,
921                sizeof(uint32_t),
922                (ComparisonFunction)SymbolWithClosestFileAddress);
923 
924     if (info.match_symbol)
925     {
926         if (info.match_offset == 0)
927         {
928             // We found an exact match!
929             return info.match_symbol;
930         }
931 
932         const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol);
933 
934         if (symbol_byte_size == 0)
935         {
936             // We weren't able to find the size of the symbol so lets just go
937             // with that match we found in our search...
938             return info.match_symbol;
939         }
940 
941         // We were able to figure out a symbol size so lets make sure our
942         // offset puts "file_addr" in the symbol's address range.
943         if (info.match_offset < symbol_byte_size)
944             return info.match_symbol;
945     }
946     return NULL;
947 }
948 
949 Symbol *
950 Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
951 {
952     Mutex::Locker locker (m_mutex);
953 
954     if (!m_addr_indexes_computed)
955         InitAddressIndexes();
956 
957     return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
958 }
959 
960