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