]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Symbol / Symtab.cpp
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/CPPLanguageRuntime.h"
20 #include "lldb/Target/ObjCLanguageRuntime.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25
26
27 Symtab::Symtab(ObjectFile *objfile) :
28     m_objfile (objfile),
29     m_symbols (),
30     m_file_addr_to_index (),
31     m_name_to_index (),
32     m_mutex (Mutex::eMutexTypeRecursive),
33     m_file_addr_to_index_computed (false),
34     m_name_indexes_computed (false)
35 {
36 }
37
38 Symtab::~Symtab()
39 {
40 }
41
42 void
43 Symtab::Reserve(size_t count)
44 {
45     // Clients should grab the mutex from this symbol table and lock it manually
46     // when calling this function to avoid performance issues.
47     m_symbols.reserve (count);
48 }
49
50 Symbol *
51 Symtab::Resize(size_t count)
52 {
53     // Clients should grab the mutex from this symbol table and lock it manually
54     // when calling this function to avoid performance issues.
55     m_symbols.resize (count);
56     return &m_symbols[0];
57 }
58
59 uint32_t
60 Symtab::AddSymbol(const Symbol& symbol)
61 {
62     // Clients should grab the mutex from this symbol table and lock it manually
63     // when calling this function to avoid performance issues.
64     uint32_t symbol_idx = m_symbols.size();
65     m_name_to_index.Clear();
66     m_file_addr_to_index.Clear();
67     m_symbols.push_back(symbol);
68     m_file_addr_to_index_computed = false;
69     m_name_indexes_computed = false;
70     return symbol_idx;
71 }
72
73 size_t
74 Symtab::GetNumSymbols() const
75 {
76     Mutex::Locker locker (m_mutex);
77     return m_symbols.size();
78 }
79
80 void
81 Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
82 {
83     Mutex::Locker locker (m_mutex);
84
85 //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
86     s->Indent();
87     const FileSpec &file_spec = m_objfile->GetFileSpec();
88     const char * object_name = NULL;
89     if (m_objfile->GetModule())
90         object_name = m_objfile->GetModule()->GetObjectName().GetCString();
91
92     if (file_spec)
93         s->Printf("Symtab, file = %s%s%s%s, num_symbols = %lu",
94         file_spec.GetPath().c_str(),
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_file_addr_to_index_computed)
148                 InitAddressIndexes();
149             const size_t num_entries = m_file_addr_to_index.GetSize();
150             for (size_t i=0; i<num_entries; ++i)
151             {
152                 s->Indent();
153                 const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
154                 m_symbols[symbol_idx].Dump(s, target, symbol_idx);
155             }
156             break;
157         }
158     }
159 }
160
161 void
162 Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
163 {
164     Mutex::Locker locker (m_mutex);
165
166     const size_t num_symbols = GetNumSymbols();
167     //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
168     s->Indent();
169     s->Printf("Symtab %lu symbol indexes (%lu symbols total):\n", indexes.size(), m_symbols.size());
170     s->IndentMore();
171
172     if (!indexes.empty())
173     {
174         std::vector<uint32_t>::const_iterator pos;
175         std::vector<uint32_t>::const_iterator end = indexes.end();
176         DumpSymbolHeader (s);
177         for (pos = indexes.begin(); pos != end; ++pos)
178         {
179             size_t idx = *pos;
180             if (idx < num_symbols)
181             {
182                 s->Indent();
183                 m_symbols[idx].Dump(s, target, idx);
184             }
185         }
186     }
187     s->IndentLess ();
188 }
189
190 void
191 Symtab::DumpSymbolHeader (Stream *s)
192 {
193     s->Indent("               Debug symbol\n");
194     s->Indent("               |Synthetic symbol\n");
195     s->Indent("               ||Externally Visible\n");
196     s->Indent("               |||\n");
197     s->Indent("Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name\n");
198     s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
199 }
200
201
202 static int
203 CompareSymbolID (const void *key, const void *p)
204 {
205     const user_id_t match_uid = *(user_id_t*) key;
206     const user_id_t symbol_uid = ((Symbol *)p)->GetID();
207     if (match_uid < symbol_uid)
208         return -1;
209     if (match_uid > symbol_uid)
210         return 1;
211     return 0;
212 }
213
214 Symbol *
215 Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
216 {
217     Mutex::Locker locker (m_mutex);
218
219     Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, 
220                                          &m_symbols[0], 
221                                          m_symbols.size(), 
222                                          (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0], 
223                                          CompareSymbolID);
224     return symbol;
225 }
226
227
228 Symbol *
229 Symtab::SymbolAtIndex(size_t idx)
230 {
231     // Clients should grab the mutex from this symbol table and lock it manually
232     // when calling this function to avoid performance issues.
233     if (idx < m_symbols.size())
234         return &m_symbols[idx];
235     return NULL;
236 }
237
238
239 const Symbol *
240 Symtab::SymbolAtIndex(size_t idx) const
241 {
242     // Clients should grab the mutex from this symbol table and lock it manually
243     // when calling this function to avoid performance issues.
244     if (idx < m_symbols.size())
245         return &m_symbols[idx];
246     return NULL;
247 }
248
249 //----------------------------------------------------------------------
250 // InitNameIndexes
251 //----------------------------------------------------------------------
252 void
253 Symtab::InitNameIndexes()
254 {
255     // Protected function, no need to lock mutex...
256     if (!m_name_indexes_computed)
257     {
258         m_name_indexes_computed = true;
259         Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
260         // Create the name index vector to be able to quickly search by name
261         const size_t num_symbols = m_symbols.size();
262 #if 1
263         m_name_to_index.Reserve (num_symbols);
264 #else
265         // TODO: benchmark this to see if we save any memory. Otherwise we
266         // will always keep the memory reserved in the vector unless we pull
267         // some STL swap magic and then recopy...
268         uint32_t actual_count = 0;
269         for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
270              pos != end; 
271              ++pos)
272         {
273             const Mangled &mangled = pos->GetMangled();
274             if (mangled.GetMangledName())
275                 ++actual_count;
276             
277             if (mangled.GetDemangledName())
278                 ++actual_count;
279         }
280
281         m_name_to_index.Reserve (actual_count);
282 #endif
283
284         NameToIndexMap::Entry entry;
285
286         // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
287         std::set<const char *> class_contexts;
288         UniqueCStringMap<uint32_t> mangled_name_to_index;
289         std::vector<const char *> symbol_contexts(num_symbols, NULL);
290
291         for (entry.value = 0; entry.value<num_symbols; ++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             {
307                 m_name_to_index.Append (entry);
308                 
309                 const SymbolType symbol_type = symbol->GetType();
310                 if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
311                 {
312                     if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
313                         (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
314                          entry.cstring[2] != 'G' && // avoid guard variables
315                          entry.cstring[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
316                     {
317                         CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
318                         entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
319                         if (entry.cstring && entry.cstring[0])
320                         {
321                             // ConstString objects permanently store the string in the pool so calling
322                             // GetCString() on the value gets us a const char * that will never go away
323                             const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
324
325                             if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
326                             {
327                                 // The first character of the demangled basename is '~' which
328                                 // means we have a class destructor. We can use this information
329                                 // to help us know what is a class and what isn't.
330                                 if (class_contexts.find(const_context) == class_contexts.end())
331                                     class_contexts.insert(const_context);
332                                 m_method_to_index.Append (entry);
333                             }
334                             else
335                             {
336                                 if (const_context && const_context[0])
337                                 {
338                                     if (class_contexts.find(const_context) != class_contexts.end())
339                                     {
340                                         // The current decl context is in our "class_contexts" which means
341                                         // this is a method on a class
342                                         m_method_to_index.Append (entry);
343                                     }
344                                     else
345                                     {
346                                         // We don't know if this is a function basename or a method,
347                                         // so put it into a temporary collection so once we are done
348                                         // we can look in class_contexts to see if each entry is a class
349                                         // or just a function and will put any remaining items into
350                                         // m_method_to_index or m_basename_to_index as needed
351                                         mangled_name_to_index.Append (entry);
352                                         symbol_contexts[entry.value] = const_context;
353                                     }
354                                 }
355                                 else
356                                 {
357                                     // No context for this function so this has to be a basename
358                                     m_basename_to_index.Append(entry);
359                                 }
360                             }
361                         }
362                     }
363                 }
364             }
365             
366             entry.cstring = mangled.GetDemangledName().GetCString();
367             if (entry.cstring && entry.cstring[0])
368                 m_name_to_index.Append (entry);
369                 
370             // If the demangled name turns out to be an ObjC name, and
371             // is a category name, add the version without categories to the index too.
372             ObjCLanguageRuntime::MethodName objc_method (entry.cstring, true);
373             if (objc_method.IsValid(true))
374             {
375                 entry.cstring = objc_method.GetSelector().GetCString();
376                 m_selector_to_index.Append (entry);
377                 
378                 ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true));
379                 if (objc_method_no_category)
380                 {
381                     entry.cstring = objc_method_no_category.GetCString();
382                     m_name_to_index.Append (entry);
383                 }
384             }
385                                                         
386         }
387         
388         size_t count;
389         if (!mangled_name_to_index.IsEmpty())
390         {
391             count = mangled_name_to_index.GetSize();
392             for (size_t i=0; i<count; ++i)
393             {
394                 if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
395                 {
396                     entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
397                     if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
398                     {
399                         m_method_to_index.Append (entry);
400                     }
401                     else
402                     {
403                         // If we got here, we have something that had a context (was inside a namespace or class)
404                         // yet we don't know if the entry
405                         m_method_to_index.Append (entry);
406                         m_basename_to_index.Append (entry);
407                     }
408                 }
409             }
410         }
411         m_name_to_index.Sort();
412         m_name_to_index.SizeToFit();
413         m_selector_to_index.Sort();
414         m_selector_to_index.SizeToFit();
415         m_basename_to_index.Sort();
416         m_basename_to_index.SizeToFit();
417         m_method_to_index.Sort();
418         m_method_to_index.SizeToFit();
419     
420 //        static StreamFile a ("/tmp/a.txt");
421 //
422 //        count = m_basename_to_index.GetSize();
423 //        if (count)
424 //        {
425 //            for (size_t i=0; i<count; ++i)
426 //            {
427 //                if (m_basename_to_index.GetValueAtIndex(i, entry.value))
428 //                    a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
429 //            }
430 //        }
431 //        count = m_method_to_index.GetSize();
432 //        if (count)
433 //        {
434 //            for (size_t i=0; i<count; ++i)
435 //            {
436 //                if (m_method_to_index.GetValueAtIndex(i, entry.value))
437 //                    a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
438 //            }
439 //        }
440     }
441 }
442
443 void
444 Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
445                                 bool add_demangled,
446                                 bool add_mangled,
447                                 NameToIndexMap &name_to_index_map) const
448 {
449     if (add_demangled || add_mangled)
450     {
451         Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
452         Mutex::Locker locker (m_mutex);
453
454         // Create the name index vector to be able to quickly search by name
455         NameToIndexMap::Entry entry;
456         const size_t num_indexes = indexes.size();
457         for (size_t i=0; i<num_indexes; ++i)
458         {
459             entry.value = indexes[i];
460             assert (i < m_symbols.size());
461             const Symbol *symbol = &m_symbols[entry.value];
462
463             const Mangled &mangled = symbol->GetMangled();
464             if (add_demangled)
465             {
466                 entry.cstring = mangled.GetDemangledName().GetCString();
467                 if (entry.cstring && entry.cstring[0])
468                     name_to_index_map.Append (entry);
469             }
470                 
471             if (add_mangled)
472             {
473                 entry.cstring = mangled.GetMangledName().GetCString();
474                 if (entry.cstring && entry.cstring[0])
475                     name_to_index_map.Append (entry);
476             }
477         }
478     }
479 }
480
481 uint32_t
482 Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
483 {
484     Mutex::Locker locker (m_mutex);
485
486     uint32_t prev_size = indexes.size();
487
488     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
489
490     for (uint32_t i = start_idx; i < count; ++i)
491     {
492         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
493             indexes.push_back(i);
494     }
495
496     return indexes.size() - prev_size;
497 }
498
499 uint32_t
500 Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
501 {
502     Mutex::Locker locker (m_mutex);
503
504     uint32_t prev_size = indexes.size();
505
506     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
507
508     for (uint32_t i = start_idx; i < count; ++i)
509     {
510         if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
511             indexes.push_back(i);
512     }
513
514     return indexes.size() - prev_size;
515 }
516
517 uint32_t
518 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
519 {
520     Mutex::Locker locker (m_mutex);
521
522     uint32_t prev_size = indexes.size();
523
524     const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
525
526     for (uint32_t i = start_idx; i < count; ++i)
527     {
528         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
529         {
530             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
531                 indexes.push_back(i);
532         }
533     }
534
535     return indexes.size() - prev_size;
536 }
537
538
539 uint32_t
540 Symtab::GetIndexForSymbol (const Symbol *symbol) const
541 {
542     const Symbol *first_symbol = &m_symbols[0];
543     if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
544         return symbol - first_symbol;
545     return UINT32_MAX;
546 }
547
548 struct SymbolSortInfo
549 {
550     const bool sort_by_load_addr;
551     const Symbol *symbols;
552 };
553
554 namespace {
555     struct SymbolIndexComparator {
556         const std::vector<Symbol>& symbols;
557         std::vector<lldb::addr_t>  &addr_cache;
558         
559         // Getting from the symbol to the Address to the File Address involves some work.
560         // Since there are potentially many symbols here, and we're using this for sorting so
561         // we're going to be computing the address many times, cache that in addr_cache.
562         // The array passed in has to be the same size as the symbols array passed into the
563         // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS.
564         // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort
565         // makes copies of the comparator it is initially passed in, and you end up spending
566         // huge amounts of time copying this array...
567         
568         SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a)  {
569             assert (symbols.size() == addr_cache.size());
570         }
571         bool operator()(uint32_t index_a, uint32_t index_b) {
572             addr_t value_a = addr_cache[index_a];
573             if (value_a == LLDB_INVALID_ADDRESS)
574             {
575                 value_a = symbols[index_a].GetAddress().GetFileAddress();
576                 addr_cache[index_a] = value_a;
577             }
578             
579             addr_t value_b = addr_cache[index_b];
580             if (value_b == LLDB_INVALID_ADDRESS)
581             {
582                 value_b = symbols[index_b].GetAddress().GetFileAddress();
583                 addr_cache[index_b] = value_b;
584             }
585             
586
587             if (value_a == value_b) {
588                 // The if the values are equal, use the original symbol user ID
589                 lldb::user_id_t uid_a = symbols[index_a].GetID();
590                 lldb::user_id_t uid_b = symbols[index_b].GetID();
591                 if (uid_a < uid_b)
592                     return true;
593                 if (uid_a > uid_b)
594                     return false;
595                 return false;
596             } else if (value_a < value_b)
597                 return true;
598         
599             return false;
600         }
601     };
602 }
603
604 void
605 Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
606 {
607     Mutex::Locker locker (m_mutex);
608
609     Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
610     // No need to sort if we have zero or one items...
611     if (indexes.size() <= 1)
612         return;
613
614     // Sort the indexes in place using std::stable_sort.
615     // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
616     // not correctness.  The indexes vector tends to be "close" to sorted, which the
617     // stable sort handles better.
618     
619     std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
620     
621     SymbolIndexComparator comparator(m_symbols, addr_cache);
622     std::stable_sort(indexes.begin(), indexes.end(), comparator);
623
624     // Remove any duplicates if requested
625     if (remove_duplicates)
626         std::unique(indexes.begin(), indexes.end());
627 }
628
629 uint32_t
630 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
631 {
632     Mutex::Locker locker (m_mutex);
633
634     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
635     if (symbol_name)
636     {
637         const char *symbol_cstr = symbol_name.GetCString();
638         if (!m_name_indexes_computed)
639             InitNameIndexes();
640
641         return m_name_to_index.GetValues (symbol_cstr, indexes);
642     }
643     return 0;
644 }
645
646 uint32_t
647 Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
648 {
649     Mutex::Locker locker (m_mutex);
650
651     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
652     if (symbol_name)
653     {
654         const size_t old_size = indexes.size();
655         if (!m_name_indexes_computed)
656             InitNameIndexes();
657
658         const char *symbol_cstr = symbol_name.GetCString();
659         
660         std::vector<uint32_t> all_name_indexes;
661         const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
662         for (size_t i=0; i<name_match_count; ++i)
663         {
664             if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
665                 indexes.push_back (all_name_indexes[i]);
666         }
667         return indexes.size() - old_size;
668     }
669     return 0;
670 }
671
672 uint32_t
673 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
674 {
675     Mutex::Locker locker (m_mutex);
676
677     if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
678     {
679         std::vector<uint32_t>::iterator pos = indexes.begin();
680         while (pos != indexes.end())
681         {
682             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
683                 ++pos;
684             else
685                 indexes.erase(pos);
686         }
687     }
688     return indexes.size();
689 }
690
691 uint32_t
692 Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
693 {
694     Mutex::Locker locker (m_mutex);
695
696     if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
697     {
698         std::vector<uint32_t>::iterator pos = indexes.begin();
699         while (pos != indexes.end())
700         {
701             if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
702                 ++pos;
703             else
704                 indexes.erase(pos);
705         }
706     }
707     return indexes.size();
708 }
709
710
711 uint32_t
712 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
713 {
714     Mutex::Locker locker (m_mutex);
715
716     uint32_t prev_size = indexes.size();
717     uint32_t sym_end = m_symbols.size();
718
719     for (uint32_t i = 0; i < sym_end; i++)
720     {
721         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
722         {
723             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
724             if (name)
725             {
726                 if (regexp.Execute (name))
727                     indexes.push_back(i);
728             }
729         }
730     }
731     return indexes.size() - prev_size;
732
733 }
734
735 uint32_t
736 Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
737 {
738     Mutex::Locker locker (m_mutex);
739
740     uint32_t prev_size = indexes.size();
741     uint32_t sym_end = m_symbols.size();
742
743     for (uint32_t i = 0; i < sym_end; i++)
744     {
745         if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
746         {
747             if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
748                 continue;
749
750             const char *name = m_symbols[i].GetMangled().GetName().AsCString();
751             if (name)
752             {
753                 if (regexp.Execute (name))
754                     indexes.push_back(i);
755             }
756         }
757     }
758     return indexes.size() - prev_size;
759
760 }
761
762 Symbol *
763 Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
764 {
765     Mutex::Locker locker (m_mutex);
766
767     const size_t count = m_symbols.size();
768     for (size_t idx = start_idx; idx < count; ++idx)
769     {
770         if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
771         {
772             if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
773             {
774                 start_idx = idx;
775                 return &m_symbols[idx];
776             }
777         }
778     }
779     return NULL;
780 }
781
782 size_t
783 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
784 {
785     Mutex::Locker locker (m_mutex);
786
787     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
788     // Initialize all of the lookup by name indexes before converting NAME
789     // to a uniqued string NAME_STR below.
790     if (!m_name_indexes_computed)
791         InitNameIndexes();
792
793     if (name)
794     {
795         // The string table did have a string that matched, but we need
796         // to check the symbols and match the symbol_type if any was given.
797         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
798     }
799     return symbol_indexes.size();
800 }
801
802 size_t
803 Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
804 {
805     Mutex::Locker locker (m_mutex);
806
807     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
808     // Initialize all of the lookup by name indexes before converting NAME
809     // to a uniqued string NAME_STR below.
810     if (!m_name_indexes_computed)
811         InitNameIndexes();
812
813     if (name)
814     {
815         // The string table did have a string that matched, but we need
816         // to check the symbols and match the symbol_type if any was given.
817         AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
818     }
819     return symbol_indexes.size();
820 }
821
822 size_t
823 Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
824 {
825     Mutex::Locker locker (m_mutex);
826
827     AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
828     return symbol_indexes.size();
829 }
830
831 Symbol *
832 Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
833 {
834     Mutex::Locker locker (m_mutex);
835
836     Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
837     if (!m_name_indexes_computed)
838         InitNameIndexes();
839
840     if (name)
841     {
842         std::vector<uint32_t> matching_indexes;
843         // The string table did have a string that matched, but we need
844         // to check the symbols and match the symbol_type if any was given.
845         if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
846         {
847             std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
848             for (pos = matching_indexes.begin(); pos != end; ++pos)
849             {
850                 Symbol *symbol = SymbolAtIndex(*pos);
851
852                 if (symbol->Compare(name, symbol_type))
853                     return symbol;
854             }
855         }
856     }
857     return NULL;
858 }
859
860 typedef struct
861 {
862     const Symtab *symtab;
863     const addr_t file_addr;
864     Symbol *match_symbol;
865     const uint32_t *match_index_ptr;
866     addr_t match_offset;
867 } SymbolSearchInfo;
868
869 static int
870 SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
871 {
872     const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
873     if (curr_symbol == NULL)
874         return -1;
875
876     const addr_t info_file_addr = info->file_addr;
877
878     // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
879     // range if the symbol has a section!
880     if (curr_symbol->ValueIsAddress())
881     {
882         const addr_t curr_file_addr = curr_symbol->GetAddress().GetFileAddress();
883         if (info_file_addr < curr_file_addr)
884             return -1;
885         if (info_file_addr > curr_file_addr)
886             return +1;
887         info->match_symbol = const_cast<Symbol *>(curr_symbol);
888         info->match_index_ptr = index_ptr;
889         return 0;
890     }
891
892     return -1;
893 }
894
895 static int
896 SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
897 {
898     const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
899     if (symbol == NULL)
900         return -1;
901
902     const addr_t info_file_addr = info->file_addr;
903     if (symbol->ValueIsAddress())
904     {
905         const addr_t curr_file_addr = symbol->GetAddress().GetFileAddress();
906         if (info_file_addr < curr_file_addr)
907             return -1;
908
909         // Since we are finding the closest symbol that is greater than or equal
910         // to 'info->file_addr' we set the symbol here. This will get set
911         // multiple times, but after the search is done it will contain the best
912         // symbol match
913         info->match_symbol = const_cast<Symbol *>(symbol);
914         info->match_index_ptr = index_ptr;
915         info->match_offset = info_file_addr - curr_file_addr;
916
917         if (info_file_addr > curr_file_addr)
918             return +1;
919         return 0;
920     }
921     return -1;
922 }
923
924 static SymbolSearchInfo
925 FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
926 {
927     SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
928     ::bsearch (&info, 
929                indexes, 
930                num_indexes, 
931                sizeof(uint32_t), 
932                (ComparisonFunction)SymbolWithClosestFileAddress);
933     return info;
934 }
935
936
937 void
938 Symtab::InitAddressIndexes()
939 {
940     // Protected function, no need to lock mutex...
941     if (!m_file_addr_to_index_computed && !m_symbols.empty())
942     {
943         m_file_addr_to_index_computed = true;
944
945         FileRangeToIndexMap::Entry entry;
946         const_iterator begin = m_symbols.begin();
947         const_iterator end = m_symbols.end();
948         for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
949         {
950             if (pos->ValueIsAddress())
951             {
952                 entry.SetRangeBase(pos->GetAddress().GetFileAddress());
953                 entry.SetByteSize(pos->GetByteSize());
954                 entry.data = std::distance(begin, pos);
955                 m_file_addr_to_index.Append(entry);
956             }
957         }
958         const size_t num_entries = m_file_addr_to_index.GetSize();
959         if (num_entries > 0)
960         {
961             m_file_addr_to_index.Sort();
962             m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges();
963         
964             // Now our last symbols might not have had sizes because there
965             // was no subsequent symbol to calculate the size from. If this is
966             // the case, then calculate the size by capping it at the end of the
967             // section in which the symbol resides
968             for (int i = num_entries - 1; i >= 0; --i)
969             {
970                 const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
971                 // As we iterate backwards, as soon as we find a symbol with a valid
972                 // byte size, we are done
973                 if (entry.GetByteSize() > 0)
974                     break;
975
976                 // Cap the size to the end of the section in which the symbol resides
977                 SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase()));
978                 if (section_sp)
979                 {
980                     const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize();
981                     const lldb::addr_t symbol_file_addr = entry.GetRangeBase();
982                     if (end_section_file_addr > symbol_file_addr)
983                     {
984                         Symbol &symbol = m_symbols[entry.data];
985
986                         symbol.SetByteSize(end_section_file_addr - symbol_file_addr);
987                         symbol.SetSizeIsSynthesized(true);
988                     }
989                 }
990             }
991             // Sort again in case the range size changes the ordering
992             m_file_addr_to_index.Sort();
993         }
994     }
995 }
996
997 void
998 Symtab::CalculateSymbolSizes ()
999 {
1000     Mutex::Locker locker (m_mutex);
1001
1002     if (!m_symbols.empty())
1003     {
1004         if (!m_file_addr_to_index_computed)
1005             InitAddressIndexes();
1006         
1007         const size_t num_entries = m_file_addr_to_index.GetSize();
1008
1009         for (size_t i = 0; i < num_entries; ++i)
1010         {
1011             // The entries in the m_file_addr_to_index have calculated the sizes already
1012             // so we will use this size if we need to.
1013             const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
1014             
1015             Symbol &symbol = m_symbols[entry.data];
1016
1017             // If the symbol size is already valid, no need to do anything
1018             if (symbol.GetByteSizeIsValid())
1019                 continue;
1020             
1021             const addr_t range_size = entry.GetByteSize();
1022             if (range_size > 0)
1023             {
1024                 symbol.SetByteSize(range_size);
1025                 symbol.SetSizeIsSynthesized(true);
1026             }
1027         }
1028     }
1029 }
1030
1031 Symbol *
1032 Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
1033 {
1034     Mutex::Locker locker (m_mutex);
1035
1036     
1037     SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
1038
1039     ::bsearch (&info, 
1040                indexes, 
1041                num_indexes, 
1042                sizeof(uint32_t), 
1043                (ComparisonFunction)SymbolWithClosestFileAddress);
1044
1045     if (info.match_symbol)
1046     {
1047         if (info.match_offset == 0)
1048         {
1049             // We found an exact match!
1050             return info.match_symbol;
1051         }
1052
1053         const size_t symbol_byte_size = info.match_symbol->GetByteSize();
1054         
1055         if (symbol_byte_size == 0)
1056         {
1057             // We weren't able to find the size of the symbol so lets just go 
1058             // with that match we found in our search...
1059             return info.match_symbol;
1060         }
1061
1062         // We were able to figure out a symbol size so lets make sure our 
1063         // offset puts "file_addr" in the symbol's address range.
1064         if (info.match_offset < symbol_byte_size)
1065             return info.match_symbol;
1066     }
1067     return NULL;
1068 }
1069
1070 Symbol *
1071 Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
1072 {
1073     Mutex::Locker locker (m_mutex);
1074
1075     if (!m_file_addr_to_index_computed)
1076         InitAddressIndexes();
1077
1078     const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr);
1079     if (entry)
1080         return SymbolAtIndex(entry->data);
1081     return NULL;
1082 }
1083
1084 void
1085 Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
1086 {
1087     // No need to protect this call using m_mutex all other method calls are
1088     // already thread safe.
1089     
1090     const bool merge_symbol_into_function = true;
1091     size_t num_indices = symbol_indexes.size();
1092     if (num_indices > 0)
1093     {
1094         SymbolContext sc;
1095         sc.module_sp = m_objfile->GetModule();
1096         for (size_t i = 0; i < num_indices; i++)
1097         {
1098             sc.symbol = SymbolAtIndex (symbol_indexes[i]);
1099             if (sc.symbol)
1100                 sc_list.AppendIfUnique(sc, merge_symbol_into_function);
1101         }
1102     }
1103 }
1104
1105
1106 size_t
1107 Symtab::FindFunctionSymbols (const ConstString &name,
1108                              uint32_t name_type_mask,
1109                              SymbolContextList& sc_list)
1110 {
1111     size_t count = 0;
1112     std::vector<uint32_t> symbol_indexes;
1113     
1114     const char *name_cstr = name.GetCString();
1115     
1116     // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
1117     assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
1118
1119     if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
1120     {
1121         std::vector<uint32_t> temp_symbol_indexes;
1122         FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes);
1123
1124         unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1125         if (temp_symbol_indexes_size > 0)
1126         {
1127             Mutex::Locker locker (m_mutex);
1128             for (unsigned i = 0; i < temp_symbol_indexes_size; i++)
1129             {
1130                 SymbolContext sym_ctx;
1131                 sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]);
1132                 if (sym_ctx.symbol)
1133                 {
1134                     switch (sym_ctx.symbol->GetType())
1135                     {
1136                     case eSymbolTypeCode:
1137                     case eSymbolTypeResolver:
1138                         symbol_indexes.push_back(temp_symbol_indexes[i]);
1139                         break;
1140                     default:
1141                         break;
1142                     }
1143                 }
1144             }
1145         }
1146     }
1147     
1148     if (name_type_mask & eFunctionNameTypeBase)
1149     {
1150         // From mangled names we can't tell what is a basename and what
1151         // is a method name, so we just treat them the same
1152         if (!m_name_indexes_computed)
1153             InitNameIndexes();
1154
1155         if (!m_basename_to_index.IsEmpty())
1156         {
1157             const UniqueCStringMap<uint32_t>::Entry *match;
1158             for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
1159                  match != NULL;
1160                  match = m_basename_to_index.FindNextValueForName(match))
1161             {
1162                 symbol_indexes.push_back(match->value);
1163             }
1164         }
1165     }
1166     
1167     if (name_type_mask & eFunctionNameTypeMethod)
1168     {
1169         if (!m_name_indexes_computed)
1170             InitNameIndexes();
1171         
1172         if (!m_method_to_index.IsEmpty())
1173         {
1174             const UniqueCStringMap<uint32_t>::Entry *match;
1175             for (match = m_method_to_index.FindFirstValueForName(name_cstr);
1176                  match != NULL;
1177                  match = m_method_to_index.FindNextValueForName(match))
1178             {
1179                 symbol_indexes.push_back(match->value);
1180             }
1181         }
1182     }
1183
1184     if (name_type_mask & eFunctionNameTypeSelector)
1185     {
1186         if (!m_name_indexes_computed)
1187             InitNameIndexes();
1188
1189         if (!m_selector_to_index.IsEmpty())
1190         {
1191             const UniqueCStringMap<uint32_t>::Entry *match;
1192             for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
1193                  match != NULL;
1194                  match = m_selector_to_index.FindNextValueForName(match))
1195             {
1196                 symbol_indexes.push_back(match->value);
1197             }
1198         }
1199     }
1200
1201     if (!symbol_indexes.empty())
1202     {
1203         std::sort(symbol_indexes.begin(), symbol_indexes.end());
1204         symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end());
1205         count = symbol_indexes.size();
1206         SymbolIndicesToSymbolContextList (symbol_indexes, sc_list);
1207     }
1208
1209     return count;
1210 }
1211