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         assert(m_objfile != NULL);
266         assert(m_objfile->GetModule() != NULL);
267 
268 #if 1
269         m_name_to_index.Reserve (count);
270 #else
271         // TODO: benchmark this to see if we save any memory. Otherwise we
272         // will always keep the memory reserved in the vector unless we pull
273         // some STL swap magic and then recopy...
274         uint32_t actual_count = 0;
275         for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
276              pos != end;
277              ++pos)
278         {
279             const Mangled &mangled = pos->GetMangled();
280             if (mangled.GetMangledName())
281                 ++actual_count;
282 
283             if (mangled.GetDemangledName())
284                 ++actual_count;
285         }
286 
287         m_name_to_index.Reserve (actual_count);
288 #endif
289 
290         UniqueCStringMap<uint32_t>::Entry entry;
291 
292         for (entry.value = 0; entry.value < count; ++entry.value)
293         {
294             const Symbol *symbol = &m_symbols[entry.value];
295 
296             // Don't let trampolines get into the lookup by name map
297             // If we ever need the trampoline symbols to be searchable by name
298             // we can remove this and then possibly add a new bool to any of the
299             // Symtab functions that lookup symbols by name to indicate if they
300             // want trampolines.
301             if (symbol->IsTrampoline())
302                 continue;
303 
304             const Mangled &mangled = symbol->GetMangled();
305             entry.cstring = mangled.GetMangledName().GetCString();
306             if (entry.cstring && entry.cstring[0])
307                 m_name_to_index.Append (entry);
308 
309             entry.cstring = mangled.GetDemangledName().GetCString();
310             if (entry.cstring && entry.cstring[0])
311                 m_name_to_index.Append (entry);
312 
313             // If the demangled name turns out to be an ObjC name, and
314             // is a category name, add the version without categories to the index too.
315             ConstString objc_base_name;
316             if (ObjCLanguageRuntime::ParseMethodName (entry.cstring,
317                                                       NULL,
318                                                       NULL,
319                                                       &objc_base_name)
320                 && !objc_base_name.IsEmpty())
321             {
322                 entry.cstring = objc_base_name.GetCString();
323                 m_name_to_index.Append (entry);
324             }
325 
326         }
327         m_name_to_index.Sort();
328     }
329 }
330 
331 uint32_t
332 Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
333 {
334     Mutex::Locker locker (m_mutex);
335 
336     uint32_t prev_size = indexes.size();
337 
338     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
339 
340     for (uint32_t i = start_idx; i < count; ++i)
341     {
342         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
343             indexes.push_back(i);
344     }
345 
346     return indexes.size() - prev_size;
347 }
348 
349 uint32_t
350 Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
351 {
352     Mutex::Locker locker (m_mutex);
353 
354     uint32_t prev_size = indexes.size();
355 
356     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
357 
358     for (uint32_t i = start_idx; i < count; ++i)
359     {
360         if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
361             indexes.push_back(i);
362     }
363 
364     return indexes.size() - prev_size;
365 }
366 
367 uint32_t
368 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
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         {
380             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
381                 indexes.push_back(i);
382         }
383     }
384 
385     return indexes.size() - prev_size;
386 }
387 
388 
389 uint32_t
390 Symtab::GetIndexForSymbol (const Symbol *symbol) const
391 {
392     const Symbol *first_symbol = &m_symbols[0];
393     if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
394         return symbol - first_symbol;
395     return UINT32_MAX;
396 }
397 
398 struct SymbolSortInfo
399 {
400     const bool sort_by_load_addr;
401     const Symbol *symbols;
402 };
403 
404 namespace {
405     struct SymbolIndexComparator {
406         const std::vector<Symbol>& symbols;
407         SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
408         bool operator()(uint32_t index_a, uint32_t index_b) {
409             addr_t value_a;
410             addr_t value_b;
411             if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
412                 value_a = symbols[index_a].GetValue ().GetOffset();
413                 value_b = symbols[index_b].GetValue ().GetOffset();
414             } else {
415                 value_a = symbols[index_a].GetValue ().GetFileAddress();
416                 value_b = symbols[index_b].GetValue ().GetFileAddress();
417             }
418 
419             if (value_a == value_b) {
420                 // The if the values are equal, use the original symbol user ID
421                 lldb::user_id_t uid_a = symbols[index_a].GetID();
422                 lldb::user_id_t uid_b = symbols[index_b].GetID();
423                 if (uid_a < uid_b)
424                     return true;
425                 if (uid_a > uid_b)
426                     return false;
427                 return false;
428             } else if (value_a < value_b)
429                 return true;
430 
431             return false;
432         }
433     };
434 }
435 
436 void
437 Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
438 {
439     Mutex::Locker locker (m_mutex);
440 
441     Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
442     // No need to sort if we have zero or one items...
443     if (indexes.size() <= 1)
444         return;
445 
446     // Sort the indexes in place using std::stable_sort.
447     // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
448     // not correctness.  The indexes vector tends to be "close" to sorted, which the
449     // stable sort handles better.
450     std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
451 
452     // Remove any duplicates if requested
453     if (remove_duplicates)
454         std::unique(indexes.begin(), indexes.end());
455 }
456 
457 uint32_t
458 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
459 {
460     Mutex::Locker locker (m_mutex);
461 
462     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
463     if (symbol_name)
464     {
465         const char *symbol_cstr = symbol_name.GetCString();
466         if (!m_name_indexes_computed)
467             InitNameIndexes();
468 
469         return m_name_to_index.GetValues (symbol_cstr, indexes);
470     }
471     return 0;
472 }
473 
474 uint32_t
475 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
476 {
477     Mutex::Locker locker (m_mutex);
478 
479     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
480     if (symbol_name)
481     {
482         const size_t old_size = indexes.size();
483         if (!m_name_indexes_computed)
484             InitNameIndexes();
485 
486         const char *symbol_cstr = symbol_name.GetCString();
487 
488         std::vector<uint32_t> all_name_indexes;
489         const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
490         for (size_t i=0; i<name_match_count; ++i)
491         {
492             if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
493                 indexes.push_back (all_name_indexes[i]);
494         }
495         return indexes.size() - old_size;
496     }
497     return 0;
498 }
499 
500 uint32_t
501 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
502 {
503     Mutex::Locker locker (m_mutex);
504 
505     if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
506     {
507         std::vector<uint32_t>::iterator pos = indexes.begin();
508         while (pos != indexes.end())
509         {
510             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
511                 ++pos;
512             else
513                 indexes.erase(pos);
514         }
515     }
516     return indexes.size();
517 }
518 
519 uint32_t
520 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
521 {
522     Mutex::Locker locker (m_mutex);
523 
524     if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
525     {
526         std::vector<uint32_t>::iterator pos = indexes.begin();
527         while (pos != indexes.end())
528         {
529             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
530                 ++pos;
531             else
532                 indexes.erase(pos);
533         }
534     }
535     return indexes.size();
536 }
537 
538 
539 uint32_t
540 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
541 {
542     Mutex::Locker locker (m_mutex);
543 
544     uint32_t prev_size = indexes.size();
545     uint32_t sym_end = m_symbols.size();
546 
547     for (int i = 0; i < sym_end; i++)
548     {
549         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
550         {
551             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
552             if (name)
553             {
554                 if (regexp.Execute (name))
555                     indexes.push_back(i);
556             }
557         }
558     }
559     return indexes.size() - prev_size;
560 
561 }
562 
563 uint32_t
564 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
565 {
566     Mutex::Locker locker (m_mutex);
567 
568     uint32_t prev_size = indexes.size();
569     uint32_t sym_end = m_symbols.size();
570 
571     for (int i = 0; i < sym_end; i++)
572     {
573         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
574         {
575             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
576                 continue;
577 
578             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
579             if (name)
580             {
581                 if (regexp.Execute (name))
582                     indexes.push_back(i);
583             }
584         }
585     }
586     return indexes.size() - prev_size;
587 
588 }
589 
590 Symbol *
591 Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
592 {
593     Mutex::Locker locker (m_mutex);
594 
595     const size_t count = m_symbols.size();
596     for (uint32_t idx = start_idx; idx < count; ++idx)
597     {
598         if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
599         {
600             if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
601             {
602                 start_idx = idx;
603                 return &m_symbols[idx];
604             }
605         }
606     }
607     return NULL;
608 }
609 
610 size_t
611 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
612 {
613     Mutex::Locker locker (m_mutex);
614 
615     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
616     // Initialize all of the lookup by name indexes before converting NAME
617     // to a uniqued string NAME_STR below.
618     if (!m_name_indexes_computed)
619         InitNameIndexes();
620 
621     if (name)
622     {
623         // The string table did have a string that matched, but we need
624         // to check the symbols and match the symbol_type if any was given.
625         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
626     }
627     return symbol_indexes.size();
628 }
629 
630 size_t
631 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
632 {
633     Mutex::Locker locker (m_mutex);
634 
635     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
636     // Initialize all of the lookup by name indexes before converting NAME
637     // to a uniqued string NAME_STR below.
638     if (!m_name_indexes_computed)
639         InitNameIndexes();
640 
641     if (name)
642     {
643         // The string table did have a string that matched, but we need
644         // to check the symbols and match the symbol_type if any was given.
645         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
646     }
647     return symbol_indexes.size();
648 }
649 
650 size_t
651 Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
652 {
653     Mutex::Locker locker (m_mutex);
654 
655     AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
656     return symbol_indexes.size();
657 }
658 
659 Symbol *
660 Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
661 {
662     Mutex::Locker locker (m_mutex);
663 
664     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
665     if (!m_name_indexes_computed)
666         InitNameIndexes();
667 
668     if (name)
669     {
670         std::vector<uint32_t> matching_indexes;
671         // The string table did have a string that matched, but we need
672         // to check the symbols and match the symbol_type if any was given.
673         if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
674         {
675             std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
676             for (pos = matching_indexes.begin(); pos != end; ++pos)
677             {
678                 Symbol *symbol = SymbolAtIndex(*pos);
679 
680                 if (symbol->Compare(name, symbol_type))
681                     return symbol;
682             }
683         }
684     }
685     return NULL;
686 }
687 
688 typedef struct
689 {
690     const Symtab *symtab;
691     const addr_t file_addr;
692     Symbol *match_symbol;
693     const uint32_t *match_index_ptr;
694     addr_t match_offset;
695 } SymbolSearchInfo;
696 
697 static int
698 SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
699 {
700     const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
701     if (curr_symbol == NULL)
702         return -1;
703 
704     const addr_t info_file_addr = info->file_addr;
705 
706     // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
707     // range if the symbol has a section!
708     const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
709     if (curr_range)
710     {
711         const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
712         if (info_file_addr < curr_file_addr)
713             return -1;
714         if (info_file_addr > curr_file_addr)
715             return +1;
716         info->match_symbol = const_cast<Symbol *>(curr_symbol);
717         info->match_index_ptr = index_ptr;
718         return 0;
719     }
720 
721     return -1;
722 }
723 
724 static int
725 SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
726 {
727     const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
728     if (symbol == NULL)
729         return -1;
730 
731     const addr_t info_file_addr = info->file_addr;
732     const AddressRange *curr_range = symbol->GetAddressRangePtr();
733     if (curr_range)
734     {
735         const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
736         if (info_file_addr < curr_file_addr)
737             return -1;
738 
739         // Since we are finding the closest symbol that is greater than or equal
740         // to 'info->file_addr' we set the symbol here. This will get set
741         // multiple times, but after the search is done it will contain the best
742         // symbol match
743         info->match_symbol = const_cast<Symbol *>(symbol);
744         info->match_index_ptr = index_ptr;
745         info->match_offset = info_file_addr - curr_file_addr;
746 
747         if (info_file_addr > curr_file_addr)
748             return +1;
749         return 0;
750     }
751     return -1;
752 }
753 
754 static SymbolSearchInfo
755 FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
756 {
757     SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
758     ::bsearch (&info,
759                indexes,
760                num_indexes,
761                sizeof(uint32_t),
762                (ComparisonFunction)SymbolWithClosestFileAddress);
763     return info;
764 }
765 
766 
767 void
768 Symtab::InitAddressIndexes()
769 {
770     // Protected function, no need to lock mutex...
771     if (!m_addr_indexes_computed && !m_symbols.empty())
772     {
773         m_addr_indexes_computed = true;
774 #if 0
775         // The old was to add only code, trampoline or data symbols...
776         AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
777         AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
778         AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
779 #else
780         // The new way adds all symbols with valid addresses that are section
781         // offset.
782         const_iterator begin = m_symbols.begin();
783         const_iterator end = m_symbols.end();
784         for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
785         {
786             if (pos->GetAddressRangePtr())
787                 m_addr_indexes.push_back (std::distance(begin, pos));
788         }
789 #endif
790         SortSymbolIndexesByValue (m_addr_indexes, false);
791         m_addr_indexes.push_back (UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
792     }
793 }
794 
795 size_t
796 Symtab::CalculateSymbolSize (Symbol *symbol)
797 {
798     Mutex::Locker locker (m_mutex);
799 
800     if (m_symbols.empty())
801         return 0;
802 
803     // Make sure this symbol is from this symbol table...
804     if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
805         return 0;
806 
807     // See if this symbol already has a byte size?
808     size_t byte_size = symbol->GetByteSize();
809 
810     if (byte_size)
811     {
812         // It does, just return it
813         return byte_size;
814     }
815 
816     // Else if this is an address based symbol, figure out the delta between
817     // it and the next address based symbol
818     if (symbol->GetAddressRangePtr())
819     {
820         if (!m_addr_indexes_computed)
821             InitAddressIndexes();
822         const size_t num_addr_indexes = m_addr_indexes.size();
823         SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
824         if (info.match_index_ptr != NULL)
825         {
826             const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
827             // We can figure out the address range of all symbols except the
828             // last one by taking the delta between the current symbol and
829             // the next symbol
830 
831             for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
832                  addr_index < num_addr_indexes;
833                  ++addr_index)
834             {
835                 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
836                 if (next_symbol == NULL)
837                     break;
838 
839                 assert (next_symbol->GetAddressRangePtr());
840                 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
841                 if (next_file_addr > curr_file_addr)
842                 {
843                     byte_size = next_file_addr - curr_file_addr;
844                     symbol->GetAddressRangePtr()->SetByteSize(byte_size);
845                     symbol->SetSizeIsSynthesized(true);
846                     break;
847                 }
848             }
849         }
850     }
851     return byte_size;
852 }
853 
854 Symbol *
855 Symtab::FindSymbolWithFileAddress (addr_t file_addr)
856 {
857     Mutex::Locker locker (m_mutex);
858 
859     if (!m_addr_indexes_computed)
860         InitAddressIndexes();
861 
862     SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
863 
864     uint32_t* match = (uint32_t*)::bsearch (&info,
865                                             &m_addr_indexes[0],
866                                             m_addr_indexes.size(),
867                                             sizeof(uint32_t),
868                                             (ComparisonFunction)SymbolWithFileAddress);
869     if (match)
870         return SymbolAtIndex (*match);
871     return NULL;
872 }
873 
874 
875 Symbol *
876 Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
877 {
878     Mutex::Locker locker (m_mutex);
879 
880     SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
881 
882     ::bsearch (&info,
883                indexes,
884                num_indexes,
885                sizeof(uint32_t),
886                (ComparisonFunction)SymbolWithClosestFileAddress);
887 
888     if (info.match_symbol)
889     {
890         if (info.match_offset == 0)
891         {
892             // We found an exact match!
893             return info.match_symbol;
894         }
895 
896         const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol);
897 
898         if (symbol_byte_size == 0)
899         {
900             // We weren't able to find the size of the symbol so lets just go
901             // with that match we found in our search...
902             return info.match_symbol;
903         }
904 
905         // We were able to figure out a symbol size so lets make sure our
906         // offset puts "file_addr" in the symbol's address range.
907         if (info.match_offset < symbol_byte_size)
908             return info.match_symbol;
909     }
910     return NULL;
911 }
912 
913 Symbol *
914 Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
915 {
916     Mutex::Locker locker (m_mutex);
917 
918     if (!m_addr_indexes_computed)
919         InitAddressIndexes();
920 
921     return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
922 }
923 
924