1254721Semaste//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include <map>
11254721Semaste
12254721Semaste#include "lldb/Core/Module.h"
13254721Semaste#include "lldb/Core/RegularExpression.h"
14254721Semaste#include "lldb/Core/Section.h"
15254721Semaste#include "lldb/Core/Timer.h"
16254721Semaste#include "lldb/Symbol/ObjectFile.h"
17254721Semaste#include "lldb/Symbol/SymbolContext.h"
18254721Semaste#include "lldb/Symbol/Symtab.h"
19254721Semaste#include "lldb/Target/CPPLanguageRuntime.h"
20254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h"
21254721Semaste
22254721Semasteusing namespace lldb;
23254721Semasteusing namespace lldb_private;
24254721Semaste
25254721Semaste
26254721Semaste
27254721SemasteSymtab::Symtab(ObjectFile *objfile) :
28254721Semaste    m_objfile (objfile),
29254721Semaste    m_symbols (),
30254721Semaste    m_file_addr_to_index (),
31254721Semaste    m_name_to_index (),
32254721Semaste    m_mutex (Mutex::eMutexTypeRecursive),
33254721Semaste    m_file_addr_to_index_computed (false),
34254721Semaste    m_name_indexes_computed (false)
35254721Semaste{
36254721Semaste}
37254721Semaste
38254721SemasteSymtab::~Symtab()
39254721Semaste{
40254721Semaste}
41254721Semaste
42254721Semastevoid
43254721SemasteSymtab::Reserve(size_t count)
44254721Semaste{
45254721Semaste    // Clients should grab the mutex from this symbol table and lock it manually
46254721Semaste    // when calling this function to avoid performance issues.
47254721Semaste    m_symbols.reserve (count);
48254721Semaste}
49254721Semaste
50254721SemasteSymbol *
51254721SemasteSymtab::Resize(size_t count)
52254721Semaste{
53254721Semaste    // Clients should grab the mutex from this symbol table and lock it manually
54254721Semaste    // when calling this function to avoid performance issues.
55254721Semaste    m_symbols.resize (count);
56254721Semaste    return &m_symbols[0];
57254721Semaste}
58254721Semaste
59254721Semasteuint32_t
60254721SemasteSymtab::AddSymbol(const Symbol& symbol)
61254721Semaste{
62254721Semaste    // Clients should grab the mutex from this symbol table and lock it manually
63254721Semaste    // when calling this function to avoid performance issues.
64254721Semaste    uint32_t symbol_idx = m_symbols.size();
65254721Semaste    m_name_to_index.Clear();
66254721Semaste    m_file_addr_to_index.Clear();
67254721Semaste    m_symbols.push_back(symbol);
68254721Semaste    m_file_addr_to_index_computed = false;
69254721Semaste    m_name_indexes_computed = false;
70254721Semaste    return symbol_idx;
71254721Semaste}
72254721Semaste
73254721Semastesize_t
74254721SemasteSymtab::GetNumSymbols() const
75254721Semaste{
76254721Semaste    Mutex::Locker locker (m_mutex);
77254721Semaste    return m_symbols.size();
78254721Semaste}
79254721Semaste
80254721Semastevoid
81254721SemasteSymtab::Dump (Stream *s, Target *target, SortOrder sort_order)
82254721Semaste{
83254721Semaste    Mutex::Locker locker (m_mutex);
84254721Semaste
85254721Semaste//    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
86254721Semaste    s->Indent();
87254721Semaste    const FileSpec &file_spec = m_objfile->GetFileSpec();
88254721Semaste    const char * object_name = NULL;
89254721Semaste    if (m_objfile->GetModule())
90254721Semaste        object_name = m_objfile->GetModule()->GetObjectName().GetCString();
91254721Semaste
92254721Semaste    if (file_spec)
93263363Semaste        s->Printf("Symtab, file = %s%s%s%s, num_symbols = %zu",
94254721Semaste        file_spec.GetPath().c_str(),
95254721Semaste        object_name ? "(" : "",
96254721Semaste        object_name ? object_name : "",
97254721Semaste        object_name ? ")" : "",
98254721Semaste        m_symbols.size());
99254721Semaste    else
100263363Semaste        s->Printf("Symtab, num_symbols = %zu", m_symbols.size());
101254721Semaste
102254721Semaste    if (!m_symbols.empty())
103254721Semaste    {
104254721Semaste        switch (sort_order)
105254721Semaste        {
106254721Semaste        case eSortOrderNone:
107254721Semaste            {
108254721Semaste                s->PutCString (":\n");
109254721Semaste                DumpSymbolHeader (s);
110254721Semaste                const_iterator begin = m_symbols.begin();
111254721Semaste                const_iterator end = m_symbols.end();
112254721Semaste                for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
113254721Semaste                {
114254721Semaste                    s->Indent();
115254721Semaste                    pos->Dump(s, target, std::distance(begin, pos));
116254721Semaste                }
117254721Semaste            }
118254721Semaste            break;
119254721Semaste
120254721Semaste        case eSortOrderByName:
121254721Semaste            {
122254721Semaste                // Although we maintain a lookup by exact name map, the table
123254721Semaste                // isn't sorted by name. So we must make the ordered symbol list
124254721Semaste                // up ourselves.
125254721Semaste                s->PutCString (" (sorted by name):\n");
126254721Semaste                DumpSymbolHeader (s);
127254721Semaste                typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol;
128254721Semaste                CStringToSymbol name_map;
129254721Semaste                for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
130254721Semaste                {
131254721Semaste                    const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString();
132254721Semaste                    if (name && name[0])
133254721Semaste                        name_map.insert (std::make_pair(name, &(*pos)));
134254721Semaste                }
135254721Semaste
136254721Semaste                for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos)
137254721Semaste                {
138254721Semaste                    s->Indent();
139254721Semaste                    pos->second->Dump (s, target, pos->second - &m_symbols[0]);
140254721Semaste                }
141254721Semaste            }
142254721Semaste            break;
143254721Semaste
144254721Semaste        case eSortOrderByAddress:
145254721Semaste            s->PutCString (" (sorted by address):\n");
146254721Semaste            DumpSymbolHeader (s);
147254721Semaste            if (!m_file_addr_to_index_computed)
148254721Semaste                InitAddressIndexes();
149254721Semaste            const size_t num_entries = m_file_addr_to_index.GetSize();
150254721Semaste            for (size_t i=0; i<num_entries; ++i)
151254721Semaste            {
152254721Semaste                s->Indent();
153254721Semaste                const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
154254721Semaste                m_symbols[symbol_idx].Dump(s, target, symbol_idx);
155254721Semaste            }
156254721Semaste            break;
157254721Semaste        }
158254721Semaste    }
159254721Semaste}
160254721Semaste
161254721Semastevoid
162254721SemasteSymtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
163254721Semaste{
164254721Semaste    Mutex::Locker locker (m_mutex);
165254721Semaste
166254721Semaste    const size_t num_symbols = GetNumSymbols();
167254721Semaste    //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
168254721Semaste    s->Indent();
169263363Semaste    s->Printf("Symtab %zu symbol indexes (%zu symbols total):\n", indexes.size(), m_symbols.size());
170254721Semaste    s->IndentMore();
171254721Semaste
172254721Semaste    if (!indexes.empty())
173254721Semaste    {
174254721Semaste        std::vector<uint32_t>::const_iterator pos;
175254721Semaste        std::vector<uint32_t>::const_iterator end = indexes.end();
176254721Semaste        DumpSymbolHeader (s);
177254721Semaste        for (pos = indexes.begin(); pos != end; ++pos)
178254721Semaste        {
179254721Semaste            size_t idx = *pos;
180254721Semaste            if (idx < num_symbols)
181254721Semaste            {
182254721Semaste                s->Indent();
183254721Semaste                m_symbols[idx].Dump(s, target, idx);
184254721Semaste            }
185254721Semaste        }
186254721Semaste    }
187254721Semaste    s->IndentLess ();
188254721Semaste}
189254721Semaste
190254721Semastevoid
191254721SemasteSymtab::DumpSymbolHeader (Stream *s)
192254721Semaste{
193254721Semaste    s->Indent("               Debug symbol\n");
194254721Semaste    s->Indent("               |Synthetic symbol\n");
195254721Semaste    s->Indent("               ||Externally Visible\n");
196254721Semaste    s->Indent("               |||\n");
197254721Semaste    s->Indent("Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name\n");
198254721Semaste    s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
199254721Semaste}
200254721Semaste
201254721Semaste
202254721Semastestatic int
203254721SemasteCompareSymbolID (const void *key, const void *p)
204254721Semaste{
205254721Semaste    const user_id_t match_uid = *(user_id_t*) key;
206254721Semaste    const user_id_t symbol_uid = ((Symbol *)p)->GetID();
207254721Semaste    if (match_uid < symbol_uid)
208254721Semaste        return -1;
209254721Semaste    if (match_uid > symbol_uid)
210254721Semaste        return 1;
211254721Semaste    return 0;
212254721Semaste}
213254721Semaste
214254721SemasteSymbol *
215254721SemasteSymtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
216254721Semaste{
217254721Semaste    Mutex::Locker locker (m_mutex);
218254721Semaste
219254721Semaste    Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
220254721Semaste                                         &m_symbols[0],
221254721Semaste                                         m_symbols.size(),
222254721Semaste                                         (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0],
223254721Semaste                                         CompareSymbolID);
224254721Semaste    return symbol;
225254721Semaste}
226254721Semaste
227254721Semaste
228254721SemasteSymbol *
229254721SemasteSymtab::SymbolAtIndex(size_t idx)
230254721Semaste{
231254721Semaste    // Clients should grab the mutex from this symbol table and lock it manually
232254721Semaste    // when calling this function to avoid performance issues.
233254721Semaste    if (idx < m_symbols.size())
234254721Semaste        return &m_symbols[idx];
235254721Semaste    return NULL;
236254721Semaste}
237254721Semaste
238254721Semaste
239254721Semasteconst Symbol *
240254721SemasteSymtab::SymbolAtIndex(size_t idx) const
241254721Semaste{
242254721Semaste    // Clients should grab the mutex from this symbol table and lock it manually
243254721Semaste    // when calling this function to avoid performance issues.
244254721Semaste    if (idx < m_symbols.size())
245254721Semaste        return &m_symbols[idx];
246254721Semaste    return NULL;
247254721Semaste}
248254721Semaste
249254721Semaste//----------------------------------------------------------------------
250254721Semaste// InitNameIndexes
251254721Semaste//----------------------------------------------------------------------
252254721Semastevoid
253254721SemasteSymtab::InitNameIndexes()
254254721Semaste{
255254721Semaste    // Protected function, no need to lock mutex...
256254721Semaste    if (!m_name_indexes_computed)
257254721Semaste    {
258254721Semaste        m_name_indexes_computed = true;
259254721Semaste        Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
260254721Semaste        // Create the name index vector to be able to quickly search by name
261254721Semaste        const size_t num_symbols = m_symbols.size();
262254721Semaste#if 1
263254721Semaste        m_name_to_index.Reserve (num_symbols);
264254721Semaste#else
265254721Semaste        // TODO: benchmark this to see if we save any memory. Otherwise we
266254721Semaste        // will always keep the memory reserved in the vector unless we pull
267254721Semaste        // some STL swap magic and then recopy...
268254721Semaste        uint32_t actual_count = 0;
269254721Semaste        for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
270254721Semaste             pos != end;
271254721Semaste             ++pos)
272254721Semaste        {
273254721Semaste            const Mangled &mangled = pos->GetMangled();
274254721Semaste            if (mangled.GetMangledName())
275254721Semaste                ++actual_count;
276254721Semaste
277254721Semaste            if (mangled.GetDemangledName())
278254721Semaste                ++actual_count;
279254721Semaste        }
280254721Semaste
281254721Semaste        m_name_to_index.Reserve (actual_count);
282254721Semaste#endif
283254721Semaste
284254721Semaste        NameToIndexMap::Entry entry;
285254721Semaste
286254721Semaste        // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
287254721Semaste        std::set<const char *> class_contexts;
288254721Semaste        UniqueCStringMap<uint32_t> mangled_name_to_index;
289254721Semaste        std::vector<const char *> symbol_contexts(num_symbols, NULL);
290254721Semaste
291254721Semaste        for (entry.value = 0; entry.value<num_symbols; ++entry.value)
292254721Semaste        {
293254721Semaste            const Symbol *symbol = &m_symbols[entry.value];
294254721Semaste
295254721Semaste            // Don't let trampolines get into the lookup by name map
296254721Semaste            // If we ever need the trampoline symbols to be searchable by name
297254721Semaste            // we can remove this and then possibly add a new bool to any of the
298254721Semaste            // Symtab functions that lookup symbols by name to indicate if they
299254721Semaste            // want trampolines.
300254721Semaste            if (symbol->IsTrampoline())
301254721Semaste                continue;
302254721Semaste
303254721Semaste            const Mangled &mangled = symbol->GetMangled();
304254721Semaste            entry.cstring = mangled.GetMangledName().GetCString();
305254721Semaste            if (entry.cstring && entry.cstring[0])
306254721Semaste            {
307254721Semaste                m_name_to_index.Append (entry);
308254721Semaste
309254721Semaste                const SymbolType symbol_type = symbol->GetType();
310254721Semaste                if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
311254721Semaste                {
312254721Semaste                    if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
313254721Semaste                        (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
314254721Semaste                         entry.cstring[2] != 'G' && // avoid guard variables
315254721Semaste                         entry.cstring[2] != 'Z'))  // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
316254721Semaste                    {
317254721Semaste                        CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
318254721Semaste                        entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
319254721Semaste                        if (entry.cstring && entry.cstring[0])
320254721Semaste                        {
321254721Semaste                            // ConstString objects permanently store the string in the pool so calling
322254721Semaste                            // GetCString() on the value gets us a const char * that will never go away
323254721Semaste                            const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
324254721Semaste
325254721Semaste                            if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
326254721Semaste                            {
327254721Semaste                                // The first character of the demangled basename is '~' which
328254721Semaste                                // means we have a class destructor. We can use this information
329254721Semaste                                // to help us know what is a class and what isn't.
330254721Semaste                                if (class_contexts.find(const_context) == class_contexts.end())
331254721Semaste                                    class_contexts.insert(const_context);
332254721Semaste                                m_method_to_index.Append (entry);
333254721Semaste                            }
334254721Semaste                            else
335254721Semaste                            {
336254721Semaste                                if (const_context && const_context[0])
337254721Semaste                                {
338254721Semaste                                    if (class_contexts.find(const_context) != class_contexts.end())
339254721Semaste                                    {
340254721Semaste                                        // The current decl context is in our "class_contexts" which means
341254721Semaste                                        // this is a method on a class
342254721Semaste                                        m_method_to_index.Append (entry);
343254721Semaste                                    }
344254721Semaste                                    else
345254721Semaste                                    {
346254721Semaste                                        // We don't know if this is a function basename or a method,
347254721Semaste                                        // so put it into a temporary collection so once we are done
348254721Semaste                                        // we can look in class_contexts to see if each entry is a class
349254721Semaste                                        // or just a function and will put any remaining items into
350254721Semaste                                        // m_method_to_index or m_basename_to_index as needed
351254721Semaste                                        mangled_name_to_index.Append (entry);
352254721Semaste                                        symbol_contexts[entry.value] = const_context;
353254721Semaste                                    }
354254721Semaste                                }
355254721Semaste                                else
356254721Semaste                                {
357254721Semaste                                    // No context for this function so this has to be a basename
358254721Semaste                                    m_basename_to_index.Append(entry);
359254721Semaste                                }
360254721Semaste                            }
361254721Semaste                        }
362254721Semaste                    }
363254721Semaste                }
364254721Semaste            }
365254721Semaste
366254721Semaste            entry.cstring = mangled.GetDemangledName().GetCString();
367254721Semaste            if (entry.cstring && entry.cstring[0])
368254721Semaste                m_name_to_index.Append (entry);
369254721Semaste
370254721Semaste            // If the demangled name turns out to be an ObjC name, and
371254721Semaste            // is a category name, add the version without categories to the index too.
372254721Semaste            ObjCLanguageRuntime::MethodName objc_method (entry.cstring, true);
373254721Semaste            if (objc_method.IsValid(true))
374254721Semaste            {
375254721Semaste                entry.cstring = objc_method.GetSelector().GetCString();
376254721Semaste                m_selector_to_index.Append (entry);
377254721Semaste
378254721Semaste                ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true));
379254721Semaste                if (objc_method_no_category)
380254721Semaste                {
381254721Semaste                    entry.cstring = objc_method_no_category.GetCString();
382254721Semaste                    m_name_to_index.Append (entry);
383254721Semaste                }
384254721Semaste            }
385254721Semaste
386254721Semaste        }
387254721Semaste
388254721Semaste        size_t count;
389254721Semaste        if (!mangled_name_to_index.IsEmpty())
390254721Semaste        {
391254721Semaste            count = mangled_name_to_index.GetSize();
392254721Semaste            for (size_t i=0; i<count; ++i)
393254721Semaste            {
394254721Semaste                if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
395254721Semaste                {
396254721Semaste                    entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
397254721Semaste                    if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
398254721Semaste                    {
399254721Semaste                        m_method_to_index.Append (entry);
400254721Semaste                    }
401254721Semaste                    else
402254721Semaste                    {
403254721Semaste                        // If we got here, we have something that had a context (was inside a namespace or class)
404254721Semaste                        // yet we don't know if the entry
405254721Semaste                        m_method_to_index.Append (entry);
406254721Semaste                        m_basename_to_index.Append (entry);
407254721Semaste                    }
408254721Semaste                }
409254721Semaste            }
410254721Semaste        }
411254721Semaste        m_name_to_index.Sort();
412254721Semaste        m_name_to_index.SizeToFit();
413254721Semaste        m_selector_to_index.Sort();
414254721Semaste        m_selector_to_index.SizeToFit();
415254721Semaste        m_basename_to_index.Sort();
416254721Semaste        m_basename_to_index.SizeToFit();
417254721Semaste        m_method_to_index.Sort();
418254721Semaste        m_method_to_index.SizeToFit();
419254721Semaste
420254721Semaste//        static StreamFile a ("/tmp/a.txt");
421254721Semaste//
422254721Semaste//        count = m_basename_to_index.GetSize();
423254721Semaste//        if (count)
424254721Semaste//        {
425254721Semaste//            for (size_t i=0; i<count; ++i)
426254721Semaste//            {
427254721Semaste//                if (m_basename_to_index.GetValueAtIndex(i, entry.value))
428254721Semaste//                    a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
429254721Semaste//            }
430254721Semaste//        }
431254721Semaste//        count = m_method_to_index.GetSize();
432254721Semaste//        if (count)
433254721Semaste//        {
434254721Semaste//            for (size_t i=0; i<count; ++i)
435254721Semaste//            {
436254721Semaste//                if (m_method_to_index.GetValueAtIndex(i, entry.value))
437254721Semaste//                    a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
438254721Semaste//            }
439254721Semaste//        }
440254721Semaste    }
441254721Semaste}
442254721Semaste
443254721Semastevoid
444254721SemasteSymtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
445254721Semaste                                bool add_demangled,
446254721Semaste                                bool add_mangled,
447254721Semaste                                NameToIndexMap &name_to_index_map) const
448254721Semaste{
449254721Semaste    if (add_demangled || add_mangled)
450254721Semaste    {
451254721Semaste        Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
452254721Semaste        Mutex::Locker locker (m_mutex);
453254721Semaste
454254721Semaste        // Create the name index vector to be able to quickly search by name
455254721Semaste        NameToIndexMap::Entry entry;
456254721Semaste        const size_t num_indexes = indexes.size();
457254721Semaste        for (size_t i=0; i<num_indexes; ++i)
458254721Semaste        {
459254721Semaste            entry.value = indexes[i];
460254721Semaste            assert (i < m_symbols.size());
461254721Semaste            const Symbol *symbol = &m_symbols[entry.value];
462254721Semaste
463254721Semaste            const Mangled &mangled = symbol->GetMangled();
464254721Semaste            if (add_demangled)
465254721Semaste            {
466254721Semaste                entry.cstring = mangled.GetDemangledName().GetCString();
467254721Semaste                if (entry.cstring && entry.cstring[0])
468254721Semaste                    name_to_index_map.Append (entry);
469254721Semaste            }
470254721Semaste
471254721Semaste            if (add_mangled)
472254721Semaste            {
473254721Semaste                entry.cstring = mangled.GetMangledName().GetCString();
474254721Semaste                if (entry.cstring && entry.cstring[0])
475254721Semaste                    name_to_index_map.Append (entry);
476254721Semaste            }
477254721Semaste        }
478254721Semaste    }
479254721Semaste}
480254721Semaste
481254721Semasteuint32_t
482254721SemasteSymtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
483254721Semaste{
484254721Semaste    Mutex::Locker locker (m_mutex);
485254721Semaste
486254721Semaste    uint32_t prev_size = indexes.size();
487254721Semaste
488254721Semaste    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
489254721Semaste
490254721Semaste    for (uint32_t i = start_idx; i < count; ++i)
491254721Semaste    {
492254721Semaste        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
493254721Semaste            indexes.push_back(i);
494254721Semaste    }
495254721Semaste
496254721Semaste    return indexes.size() - prev_size;
497254721Semaste}
498254721Semaste
499254721Semasteuint32_t
500254721SemasteSymtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
501254721Semaste{
502254721Semaste    Mutex::Locker locker (m_mutex);
503254721Semaste
504254721Semaste    uint32_t prev_size = indexes.size();
505254721Semaste
506254721Semaste    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
507254721Semaste
508254721Semaste    for (uint32_t i = start_idx; i < count; ++i)
509254721Semaste    {
510254721Semaste        if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
511254721Semaste            indexes.push_back(i);
512254721Semaste    }
513254721Semaste
514254721Semaste    return indexes.size() - prev_size;
515254721Semaste}
516254721Semaste
517254721Semasteuint32_t
518254721SemasteSymtab::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
519254721Semaste{
520254721Semaste    Mutex::Locker locker (m_mutex);
521254721Semaste
522254721Semaste    uint32_t prev_size = indexes.size();
523254721Semaste
524254721Semaste    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
525254721Semaste
526254721Semaste    for (uint32_t i = start_idx; i < count; ++i)
527254721Semaste    {
528254721Semaste        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
529254721Semaste        {
530254721Semaste            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
531254721Semaste                indexes.push_back(i);
532254721Semaste        }
533254721Semaste    }
534254721Semaste
535254721Semaste    return indexes.size() - prev_size;
536254721Semaste}
537254721Semaste
538254721Semaste
539254721Semasteuint32_t
540254721SemasteSymtab::GetIndexForSymbol (const Symbol *symbol) const
541254721Semaste{
542254721Semaste    const Symbol *first_symbol = &m_symbols[0];
543254721Semaste    if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
544254721Semaste        return symbol - first_symbol;
545254721Semaste    return UINT32_MAX;
546254721Semaste}
547254721Semaste
548254721Semastestruct SymbolSortInfo
549254721Semaste{
550254721Semaste    const bool sort_by_load_addr;
551254721Semaste    const Symbol *symbols;
552254721Semaste};
553254721Semaste
554254721Semastenamespace {
555254721Semaste    struct SymbolIndexComparator {
556254721Semaste        const std::vector<Symbol>& symbols;
557254721Semaste        std::vector<lldb::addr_t>  &addr_cache;
558254721Semaste
559254721Semaste        // Getting from the symbol to the Address to the File Address involves some work.
560254721Semaste        // Since there are potentially many symbols here, and we're using this for sorting so
561254721Semaste        // we're going to be computing the address many times, cache that in addr_cache.
562254721Semaste        // The array passed in has to be the same size as the symbols array passed into the
563254721Semaste        // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS.
564254721Semaste        // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort
565254721Semaste        // makes copies of the comparator it is initially passed in, and you end up spending
566254721Semaste        // huge amounts of time copying this array...
567254721Semaste
568254721Semaste        SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a)  {
569254721Semaste            assert (symbols.size() == addr_cache.size());
570254721Semaste        }
571254721Semaste        bool operator()(uint32_t index_a, uint32_t index_b) {
572254721Semaste            addr_t value_a = addr_cache[index_a];
573254721Semaste            if (value_a == LLDB_INVALID_ADDRESS)
574254721Semaste            {
575254721Semaste                value_a = symbols[index_a].GetAddress().GetFileAddress();
576254721Semaste                addr_cache[index_a] = value_a;
577254721Semaste            }
578254721Semaste
579254721Semaste            addr_t value_b = addr_cache[index_b];
580254721Semaste            if (value_b == LLDB_INVALID_ADDRESS)
581254721Semaste            {
582254721Semaste                value_b = symbols[index_b].GetAddress().GetFileAddress();
583254721Semaste                addr_cache[index_b] = value_b;
584254721Semaste            }
585254721Semaste
586254721Semaste
587254721Semaste            if (value_a == value_b) {
588254721Semaste                // The if the values are equal, use the original symbol user ID
589254721Semaste                lldb::user_id_t uid_a = symbols[index_a].GetID();
590254721Semaste                lldb::user_id_t uid_b = symbols[index_b].GetID();
591254721Semaste                if (uid_a < uid_b)
592254721Semaste                    return true;
593254721Semaste                if (uid_a > uid_b)
594254721Semaste                    return false;
595254721Semaste                return false;
596254721Semaste            } else if (value_a < value_b)
597254721Semaste                return true;
598254721Semaste
599254721Semaste            return false;
600254721Semaste        }
601254721Semaste    };
602254721Semaste}
603254721Semaste
604254721Semastevoid
605254721SemasteSymtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
606254721Semaste{
607254721Semaste    Mutex::Locker locker (m_mutex);
608254721Semaste
609254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
610254721Semaste    // No need to sort if we have zero or one items...
611254721Semaste    if (indexes.size() <= 1)
612254721Semaste        return;
613254721Semaste
614254721Semaste    // Sort the indexes in place using std::stable_sort.
615254721Semaste    // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
616254721Semaste    // not correctness.  The indexes vector tends to be "close" to sorted, which the
617254721Semaste    // stable sort handles better.
618254721Semaste
619254721Semaste    std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
620254721Semaste
621254721Semaste    SymbolIndexComparator comparator(m_symbols, addr_cache);
622254721Semaste    std::stable_sort(indexes.begin(), indexes.end(), comparator);
623254721Semaste
624254721Semaste    // Remove any duplicates if requested
625254721Semaste    if (remove_duplicates)
626254721Semaste        std::unique(indexes.begin(), indexes.end());
627254721Semaste}
628254721Semaste
629254721Semasteuint32_t
630254721SemasteSymtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
631254721Semaste{
632254721Semaste    Mutex::Locker locker (m_mutex);
633254721Semaste
634254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
635254721Semaste    if (symbol_name)
636254721Semaste    {
637254721Semaste        const char *symbol_cstr = symbol_name.GetCString();
638254721Semaste        if (!m_name_indexes_computed)
639254721Semaste            InitNameIndexes();
640254721Semaste
641254721Semaste        return m_name_to_index.GetValues (symbol_cstr, indexes);
642254721Semaste    }
643254721Semaste    return 0;
644254721Semaste}
645254721Semaste
646254721Semasteuint32_t
647254721SemasteSymtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
648254721Semaste{
649254721Semaste    Mutex::Locker locker (m_mutex);
650254721Semaste
651254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
652254721Semaste    if (symbol_name)
653254721Semaste    {
654254721Semaste        const size_t old_size = indexes.size();
655254721Semaste        if (!m_name_indexes_computed)
656254721Semaste            InitNameIndexes();
657254721Semaste
658254721Semaste        const char *symbol_cstr = symbol_name.GetCString();
659254721Semaste
660254721Semaste        std::vector<uint32_t> all_name_indexes;
661254721Semaste        const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
662254721Semaste        for (size_t i=0; i<name_match_count; ++i)
663254721Semaste        {
664254721Semaste            if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
665254721Semaste                indexes.push_back (all_name_indexes[i]);
666254721Semaste        }
667254721Semaste        return indexes.size() - old_size;
668254721Semaste    }
669254721Semaste    return 0;
670254721Semaste}
671254721Semaste
672254721Semasteuint32_t
673254721SemasteSymtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
674254721Semaste{
675254721Semaste    Mutex::Locker locker (m_mutex);
676254721Semaste
677254721Semaste    if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
678254721Semaste    {
679254721Semaste        std::vector<uint32_t>::iterator pos = indexes.begin();
680254721Semaste        while (pos != indexes.end())
681254721Semaste        {
682254721Semaste            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
683254721Semaste                ++pos;
684254721Semaste            else
685263363Semaste                pos = indexes.erase(pos);
686254721Semaste        }
687254721Semaste    }
688254721Semaste    return indexes.size();
689254721Semaste}
690254721Semaste
691254721Semasteuint32_t
692254721SemasteSymtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
693254721Semaste{
694254721Semaste    Mutex::Locker locker (m_mutex);
695254721Semaste
696254721Semaste    if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
697254721Semaste    {
698254721Semaste        std::vector<uint32_t>::iterator pos = indexes.begin();
699254721Semaste        while (pos != indexes.end())
700254721Semaste        {
701254721Semaste            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
702254721Semaste                ++pos;
703254721Semaste            else
704263363Semaste                pos = indexes.erase(pos);
705254721Semaste        }
706254721Semaste    }
707254721Semaste    return indexes.size();
708254721Semaste}
709254721Semaste
710254721Semaste
711254721Semasteuint32_t
712254721SemasteSymtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
713254721Semaste{
714254721Semaste    Mutex::Locker locker (m_mutex);
715254721Semaste
716254721Semaste    uint32_t prev_size = indexes.size();
717254721Semaste    uint32_t sym_end = m_symbols.size();
718254721Semaste
719254721Semaste    for (uint32_t i = 0; i < sym_end; i++)
720254721Semaste    {
721254721Semaste        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
722254721Semaste        {
723254721Semaste            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
724254721Semaste            if (name)
725254721Semaste            {
726254721Semaste                if (regexp.Execute (name))
727254721Semaste                    indexes.push_back(i);
728254721Semaste            }
729254721Semaste        }
730254721Semaste    }
731254721Semaste    return indexes.size() - prev_size;
732254721Semaste
733254721Semaste}
734254721Semaste
735254721Semasteuint32_t
736254721SemasteSymtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
737254721Semaste{
738254721Semaste    Mutex::Locker locker (m_mutex);
739254721Semaste
740254721Semaste    uint32_t prev_size = indexes.size();
741254721Semaste    uint32_t sym_end = m_symbols.size();
742254721Semaste
743254721Semaste    for (uint32_t i = 0; i < sym_end; i++)
744254721Semaste    {
745254721Semaste        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
746254721Semaste        {
747254721Semaste            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
748254721Semaste                continue;
749254721Semaste
750254721Semaste            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
751254721Semaste            if (name)
752254721Semaste            {
753254721Semaste                if (regexp.Execute (name))
754254721Semaste                    indexes.push_back(i);
755254721Semaste            }
756254721Semaste        }
757254721Semaste    }
758254721Semaste    return indexes.size() - prev_size;
759254721Semaste
760254721Semaste}
761254721Semaste
762254721SemasteSymbol *
763254721SemasteSymtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
764254721Semaste{
765254721Semaste    Mutex::Locker locker (m_mutex);
766254721Semaste
767254721Semaste    const size_t count = m_symbols.size();
768254721Semaste    for (size_t idx = start_idx; idx < count; ++idx)
769254721Semaste    {
770254721Semaste        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
771254721Semaste        {
772254721Semaste            if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
773254721Semaste            {
774254721Semaste                start_idx = idx;
775254721Semaste                return &m_symbols[idx];
776254721Semaste            }
777254721Semaste        }
778254721Semaste    }
779254721Semaste    return NULL;
780254721Semaste}
781254721Semaste
782254721Semastesize_t
783254721SemasteSymtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
784254721Semaste{
785254721Semaste    Mutex::Locker locker (m_mutex);
786254721Semaste
787254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
788254721Semaste    // Initialize all of the lookup by name indexes before converting NAME
789254721Semaste    // to a uniqued string NAME_STR below.
790254721Semaste    if (!m_name_indexes_computed)
791254721Semaste        InitNameIndexes();
792254721Semaste
793254721Semaste    if (name)
794254721Semaste    {
795254721Semaste        // The string table did have a string that matched, but we need
796254721Semaste        // to check the symbols and match the symbol_type if any was given.
797254721Semaste        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
798254721Semaste    }
799254721Semaste    return symbol_indexes.size();
800254721Semaste}
801254721Semaste
802254721Semastesize_t
803254721SemasteSymtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
804254721Semaste{
805254721Semaste    Mutex::Locker locker (m_mutex);
806254721Semaste
807254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
808254721Semaste    // Initialize all of the lookup by name indexes before converting NAME
809254721Semaste    // to a uniqued string NAME_STR below.
810254721Semaste    if (!m_name_indexes_computed)
811254721Semaste        InitNameIndexes();
812254721Semaste
813254721Semaste    if (name)
814254721Semaste    {
815254721Semaste        // The string table did have a string that matched, but we need
816254721Semaste        // to check the symbols and match the symbol_type if any was given.
817254721Semaste        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
818254721Semaste    }
819254721Semaste    return symbol_indexes.size();
820254721Semaste}
821254721Semaste
822254721Semastesize_t
823254721SemasteSymtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
824254721Semaste{
825254721Semaste    Mutex::Locker locker (m_mutex);
826254721Semaste
827254721Semaste    AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
828254721Semaste    return symbol_indexes.size();
829254721Semaste}
830254721Semaste
831254721SemasteSymbol *
832254721SemasteSymtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
833254721Semaste{
834254721Semaste    Mutex::Locker locker (m_mutex);
835254721Semaste
836254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
837254721Semaste    if (!m_name_indexes_computed)
838254721Semaste        InitNameIndexes();
839254721Semaste
840254721Semaste    if (name)
841254721Semaste    {
842254721Semaste        std::vector<uint32_t> matching_indexes;
843254721Semaste        // The string table did have a string that matched, but we need
844254721Semaste        // to check the symbols and match the symbol_type if any was given.
845254721Semaste        if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
846254721Semaste        {
847254721Semaste            std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
848254721Semaste            for (pos = matching_indexes.begin(); pos != end; ++pos)
849254721Semaste            {
850254721Semaste                Symbol *symbol = SymbolAtIndex(*pos);
851254721Semaste
852254721Semaste                if (symbol->Compare(name, symbol_type))
853254721Semaste                    return symbol;
854254721Semaste            }
855254721Semaste        }
856254721Semaste    }
857254721Semaste    return NULL;
858254721Semaste}
859254721Semaste
860254721Semastetypedef struct
861254721Semaste{
862254721Semaste    const Symtab *symtab;
863254721Semaste    const addr_t file_addr;
864254721Semaste    Symbol *match_symbol;
865254721Semaste    const uint32_t *match_index_ptr;
866254721Semaste    addr_t match_offset;
867254721Semaste} SymbolSearchInfo;
868254721Semaste
869254721Semastestatic int
870254721SemasteSymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
871254721Semaste{
872254721Semaste    const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
873254721Semaste    if (curr_symbol == NULL)
874254721Semaste        return -1;
875254721Semaste
876254721Semaste    const addr_t info_file_addr = info->file_addr;
877254721Semaste
878254721Semaste    // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
879254721Semaste    // range if the symbol has a section!
880254721Semaste    if (curr_symbol->ValueIsAddress())
881254721Semaste    {
882254721Semaste        const addr_t curr_file_addr = curr_symbol->GetAddress().GetFileAddress();
883254721Semaste        if (info_file_addr < curr_file_addr)
884254721Semaste            return -1;
885254721Semaste        if (info_file_addr > curr_file_addr)
886254721Semaste            return +1;
887254721Semaste        info->match_symbol = const_cast<Symbol *>(curr_symbol);
888254721Semaste        info->match_index_ptr = index_ptr;
889254721Semaste        return 0;
890254721Semaste    }
891254721Semaste
892254721Semaste    return -1;
893254721Semaste}
894254721Semaste
895254721Semastestatic int
896254721SemasteSymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
897254721Semaste{
898254721Semaste    const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
899254721Semaste    if (symbol == NULL)
900254721Semaste        return -1;
901254721Semaste
902254721Semaste    const addr_t info_file_addr = info->file_addr;
903254721Semaste    if (symbol->ValueIsAddress())
904254721Semaste    {
905254721Semaste        const addr_t curr_file_addr = symbol->GetAddress().GetFileAddress();
906254721Semaste        if (info_file_addr < curr_file_addr)
907254721Semaste            return -1;
908254721Semaste
909254721Semaste        // Since we are finding the closest symbol that is greater than or equal
910254721Semaste        // to 'info->file_addr' we set the symbol here. This will get set
911254721Semaste        // multiple times, but after the search is done it will contain the best
912254721Semaste        // symbol match
913254721Semaste        info->match_symbol = const_cast<Symbol *>(symbol);
914254721Semaste        info->match_index_ptr = index_ptr;
915254721Semaste        info->match_offset = info_file_addr - curr_file_addr;
916254721Semaste
917254721Semaste        if (info_file_addr > curr_file_addr)
918254721Semaste            return +1;
919254721Semaste        return 0;
920254721Semaste    }
921254721Semaste    return -1;
922254721Semaste}
923254721Semaste
924254721Semastestatic SymbolSearchInfo
925254721SemasteFindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
926254721Semaste{
927254721Semaste    SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
928254721Semaste    ::bsearch (&info,
929254721Semaste               indexes,
930254721Semaste               num_indexes,
931254721Semaste               sizeof(uint32_t),
932254721Semaste               (ComparisonFunction)SymbolWithClosestFileAddress);
933254721Semaste    return info;
934254721Semaste}
935254721Semaste
936254721Semaste
937254721Semastevoid
938254721SemasteSymtab::InitAddressIndexes()
939254721Semaste{
940254721Semaste    // Protected function, no need to lock mutex...
941254721Semaste    if (!m_file_addr_to_index_computed && !m_symbols.empty())
942254721Semaste    {
943254721Semaste        m_file_addr_to_index_computed = true;
944254721Semaste
945254721Semaste        FileRangeToIndexMap::Entry entry;
946254721Semaste        const_iterator begin = m_symbols.begin();
947254721Semaste        const_iterator end = m_symbols.end();
948254721Semaste        for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
949254721Semaste        {
950254721Semaste            if (pos->ValueIsAddress())
951254721Semaste            {
952254721Semaste                entry.SetRangeBase(pos->GetAddress().GetFileAddress());
953254721Semaste                entry.SetByteSize(pos->GetByteSize());
954254721Semaste                entry.data = std::distance(begin, pos);
955254721Semaste                m_file_addr_to_index.Append(entry);
956254721Semaste            }
957254721Semaste        }
958254721Semaste        const size_t num_entries = m_file_addr_to_index.GetSize();
959254721Semaste        if (num_entries > 0)
960254721Semaste        {
961254721Semaste            m_file_addr_to_index.Sort();
962254721Semaste            m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges();
963254721Semaste
964254721Semaste            // Now our last symbols might not have had sizes because there
965254721Semaste            // was no subsequent symbol to calculate the size from. If this is
966254721Semaste            // the case, then calculate the size by capping it at the end of the
967254721Semaste            // section in which the symbol resides
968254721Semaste            for (int i = num_entries - 1; i >= 0; --i)
969254721Semaste            {
970254721Semaste                const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
971254721Semaste                // As we iterate backwards, as soon as we find a symbol with a valid
972254721Semaste                // byte size, we are done
973254721Semaste                if (entry.GetByteSize() > 0)
974254721Semaste                    break;
975254721Semaste
976254721Semaste                // Cap the size to the end of the section in which the symbol resides
977254721Semaste                SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase()));
978254721Semaste                if (section_sp)
979254721Semaste                {
980254721Semaste                    const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize();
981254721Semaste                    const lldb::addr_t symbol_file_addr = entry.GetRangeBase();
982254721Semaste                    if (end_section_file_addr > symbol_file_addr)
983254721Semaste                    {
984254721Semaste                        Symbol &symbol = m_symbols[entry.data];
985254721Semaste
986254721Semaste                        symbol.SetByteSize(end_section_file_addr - symbol_file_addr);
987254721Semaste                        symbol.SetSizeIsSynthesized(true);
988254721Semaste                    }
989254721Semaste                }
990254721Semaste            }
991254721Semaste            // Sort again in case the range size changes the ordering
992254721Semaste            m_file_addr_to_index.Sort();
993254721Semaste        }
994254721Semaste    }
995254721Semaste}
996254721Semaste
997254721Semastevoid
998254721SemasteSymtab::CalculateSymbolSizes ()
999254721Semaste{
1000254721Semaste    Mutex::Locker locker (m_mutex);
1001254721Semaste
1002254721Semaste    if (!m_symbols.empty())
1003254721Semaste    {
1004254721Semaste        if (!m_file_addr_to_index_computed)
1005254721Semaste            InitAddressIndexes();
1006254721Semaste
1007254721Semaste        const size_t num_entries = m_file_addr_to_index.GetSize();
1008254721Semaste
1009254721Semaste        for (size_t i = 0; i < num_entries; ++i)
1010254721Semaste        {
1011254721Semaste            // The entries in the m_file_addr_to_index have calculated the sizes already
1012254721Semaste            // so we will use this size if we need to.
1013254721Semaste            const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
1014254721Semaste
1015254721Semaste            Symbol &symbol = m_symbols[entry.data];
1016254721Semaste
1017254721Semaste            // If the symbol size is already valid, no need to do anything
1018254721Semaste            if (symbol.GetByteSizeIsValid())
1019254721Semaste                continue;
1020254721Semaste
1021254721Semaste            const addr_t range_size = entry.GetByteSize();
1022254721Semaste            if (range_size > 0)
1023254721Semaste            {
1024254721Semaste                symbol.SetByteSize(range_size);
1025254721Semaste                symbol.SetSizeIsSynthesized(true);
1026254721Semaste            }
1027254721Semaste        }
1028254721Semaste    }
1029254721Semaste}
1030254721Semaste
1031254721SemasteSymbol *
1032254721SemasteSymtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
1033254721Semaste{
1034254721Semaste    Mutex::Locker locker (m_mutex);
1035254721Semaste
1036254721Semaste
1037254721Semaste    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
1038254721Semaste
1039254721Semaste    ::bsearch (&info,
1040254721Semaste               indexes,
1041254721Semaste               num_indexes,
1042254721Semaste               sizeof(uint32_t),
1043254721Semaste               (ComparisonFunction)SymbolWithClosestFileAddress);
1044254721Semaste
1045254721Semaste    if (info.match_symbol)
1046254721Semaste    {
1047254721Semaste        if (info.match_offset == 0)
1048254721Semaste        {
1049254721Semaste            // We found an exact match!
1050254721Semaste            return info.match_symbol;
1051254721Semaste        }
1052254721Semaste
1053254721Semaste        const size_t symbol_byte_size = info.match_symbol->GetByteSize();
1054254721Semaste
1055254721Semaste        if (symbol_byte_size == 0)
1056254721Semaste        {
1057254721Semaste            // We weren't able to find the size of the symbol so lets just go
1058254721Semaste            // with that match we found in our search...
1059254721Semaste            return info.match_symbol;
1060254721Semaste        }
1061254721Semaste
1062254721Semaste        // We were able to figure out a symbol size so lets make sure our
1063254721Semaste        // offset puts "file_addr" in the symbol's address range.
1064254721Semaste        if (info.match_offset < symbol_byte_size)
1065254721Semaste            return info.match_symbol;
1066254721Semaste    }
1067254721Semaste    return NULL;
1068254721Semaste}
1069254721Semaste
1070254721SemasteSymbol *
1071254721SemasteSymtab::FindSymbolContainingFileAddress (addr_t file_addr)
1072254721Semaste{
1073254721Semaste    Mutex::Locker locker (m_mutex);
1074254721Semaste
1075254721Semaste    if (!m_file_addr_to_index_computed)
1076254721Semaste        InitAddressIndexes();
1077254721Semaste
1078254721Semaste    const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr);
1079254721Semaste    if (entry)
1080254721Semaste        return SymbolAtIndex(entry->data);
1081254721Semaste    return NULL;
1082254721Semaste}
1083254721Semaste
1084254721Semastevoid
1085254721SemasteSymtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
1086254721Semaste{
1087254721Semaste    // No need to protect this call using m_mutex all other method calls are
1088254721Semaste    // already thread safe.
1089254721Semaste
1090254721Semaste    const bool merge_symbol_into_function = true;
1091254721Semaste    size_t num_indices = symbol_indexes.size();
1092254721Semaste    if (num_indices > 0)
1093254721Semaste    {
1094254721Semaste        SymbolContext sc;
1095254721Semaste        sc.module_sp = m_objfile->GetModule();
1096254721Semaste        for (size_t i = 0; i < num_indices; i++)
1097254721Semaste        {
1098254721Semaste            sc.symbol = SymbolAtIndex (symbol_indexes[i]);
1099254721Semaste            if (sc.symbol)
1100254721Semaste                sc_list.AppendIfUnique(sc, merge_symbol_into_function);
1101254721Semaste        }
1102254721Semaste    }
1103254721Semaste}
1104254721Semaste
1105254721Semaste
1106254721Semastesize_t
1107254721SemasteSymtab::FindFunctionSymbols (const ConstString &name,
1108254721Semaste                             uint32_t name_type_mask,
1109254721Semaste                             SymbolContextList& sc_list)
1110254721Semaste{
1111254721Semaste    size_t count = 0;
1112254721Semaste    std::vector<uint32_t> symbol_indexes;
1113254721Semaste
1114254721Semaste    const char *name_cstr = name.GetCString();
1115254721Semaste
1116254721Semaste    // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
1117254721Semaste    assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
1118254721Semaste
1119254721Semaste    if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
1120254721Semaste    {
1121254721Semaste        std::vector<uint32_t> temp_symbol_indexes;
1122254721Semaste        FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes);
1123254721Semaste
1124254721Semaste        unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1125254721Semaste        if (temp_symbol_indexes_size > 0)
1126254721Semaste        {
1127254721Semaste            Mutex::Locker locker (m_mutex);
1128254721Semaste            for (unsigned i = 0; i < temp_symbol_indexes_size; i++)
1129254721Semaste            {
1130254721Semaste                SymbolContext sym_ctx;
1131254721Semaste                sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]);
1132254721Semaste                if (sym_ctx.symbol)
1133254721Semaste                {
1134254721Semaste                    switch (sym_ctx.symbol->GetType())
1135254721Semaste                    {
1136254721Semaste                    case eSymbolTypeCode:
1137254721Semaste                    case eSymbolTypeResolver:
1138263363Semaste                    case eSymbolTypeReExported:
1139254721Semaste                        symbol_indexes.push_back(temp_symbol_indexes[i]);
1140254721Semaste                        break;
1141254721Semaste                    default:
1142254721Semaste                        break;
1143254721Semaste                    }
1144254721Semaste                }
1145254721Semaste            }
1146254721Semaste        }
1147254721Semaste    }
1148254721Semaste
1149254721Semaste    if (name_type_mask & eFunctionNameTypeBase)
1150254721Semaste    {
1151254721Semaste        // From mangled names we can't tell what is a basename and what
1152254721Semaste        // is a method name, so we just treat them the same
1153254721Semaste        if (!m_name_indexes_computed)
1154254721Semaste            InitNameIndexes();
1155254721Semaste
1156254721Semaste        if (!m_basename_to_index.IsEmpty())
1157254721Semaste        {
1158254721Semaste            const UniqueCStringMap<uint32_t>::Entry *match;
1159254721Semaste            for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
1160254721Semaste                 match != NULL;
1161254721Semaste                 match = m_basename_to_index.FindNextValueForName(match))
1162254721Semaste            {
1163254721Semaste                symbol_indexes.push_back(match->value);
1164254721Semaste            }
1165254721Semaste        }
1166254721Semaste    }
1167254721Semaste
1168254721Semaste    if (name_type_mask & eFunctionNameTypeMethod)
1169254721Semaste    {
1170254721Semaste        if (!m_name_indexes_computed)
1171254721Semaste            InitNameIndexes();
1172254721Semaste
1173254721Semaste        if (!m_method_to_index.IsEmpty())
1174254721Semaste        {
1175254721Semaste            const UniqueCStringMap<uint32_t>::Entry *match;
1176254721Semaste            for (match = m_method_to_index.FindFirstValueForName(name_cstr);
1177254721Semaste                 match != NULL;
1178254721Semaste                 match = m_method_to_index.FindNextValueForName(match))
1179254721Semaste            {
1180254721Semaste                symbol_indexes.push_back(match->value);
1181254721Semaste            }
1182254721Semaste        }
1183254721Semaste    }
1184254721Semaste
1185254721Semaste    if (name_type_mask & eFunctionNameTypeSelector)
1186254721Semaste    {
1187254721Semaste        if (!m_name_indexes_computed)
1188254721Semaste            InitNameIndexes();
1189254721Semaste
1190254721Semaste        if (!m_selector_to_index.IsEmpty())
1191254721Semaste        {
1192254721Semaste            const UniqueCStringMap<uint32_t>::Entry *match;
1193254721Semaste            for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
1194254721Semaste                 match != NULL;
1195254721Semaste                 match = m_selector_to_index.FindNextValueForName(match))
1196254721Semaste            {
1197254721Semaste                symbol_indexes.push_back(match->value);
1198254721Semaste            }
1199254721Semaste        }
1200254721Semaste    }
1201254721Semaste
1202254721Semaste    if (!symbol_indexes.empty())
1203254721Semaste    {
1204254721Semaste        std::sort(symbol_indexes.begin(), symbol_indexes.end());
1205254721Semaste        symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end());
1206254721Semaste        count = symbol_indexes.size();
1207254721Semaste        SymbolIndicesToSymbolContextList (symbol_indexes, sc_list);
1208254721Semaste    }
1209254721Semaste
1210254721Semaste    return count;
1211254721Semaste}
1212254721Semaste
1213