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