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