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