Symtab.cpp revision c3d68556a5ae14219eb7638dade1799ab94b69fe
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// License. See LICENSE.TXT for details.
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//===----------------------------------------------------------------------===//
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <map>
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "lldb/Core/Module.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "lldb/Core/RegularExpression.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "lldb/Core/Timer.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "lldb/Symbol/ObjectFile.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "lldb/Symbol/Symtab.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using namespace lldb;
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using namespace lldb_private;
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Symtab::Symtab(ObjectFile *objfile) :
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    m_objfile(objfile),
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    m_symbols(),
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    m_addr_indexes(),
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    m_name_to_index()
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Symtab::~Symtab()
32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch{
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Symtab::Reserve(uint32_t count)
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles){
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    m_symbols.reserve (count);
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Symbol *
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Symtab::Resize(uint32_t count)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    m_symbols.resize (count);
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return &m_symbols[0];
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)uint32_t
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSymtab::AddSymbol(const Symbol& symbol)
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    uint32_t symbol_idx = m_symbols.size();
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    m_name_to_index.Clear();
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    m_addr_indexes.clear();
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    m_symbols.push_back(symbol);
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return symbol_idx;
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Symtab::GetNumSymbols() const
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return m_symbols.size();
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Symtab::Dump(Stream *s, Process *process) const
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const_iterator pos;
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    s->Indent();
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const FileSpec &file_spec = m_objfile->GetFileSpec();
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const char * object_name = NULL;
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (m_objfile->GetModule())
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        object_name = m_objfile->GetModule()->GetObjectName().GetCString();
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (file_spec)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u:\n",
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        file_spec.GetDirectory().AsCString(),
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        file_spec.GetFilename().AsCString(),
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        object_name ? "(" : "",
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        object_name ? object_name : "",
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        object_name ? ")" : "",
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        m_symbols.size());
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        s->Printf("Symtab, num_symbols = %u:\n", m_symbols.size());
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    s->IndentMore();
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!m_symbols.empty())
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    {
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const_iterator begin = m_symbols.begin();
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const_iterator end = m_symbols.end();
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        DumpSymbolHeader (s);
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for (pos = m_symbols.begin(); pos != end; ++pos)
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        {
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            s->Indent();
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            pos->Dump(s, process, std::distance(begin, pos));
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        }
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    s->IndentLess ();
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void
102a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSymtab::Dump(Stream *s, Process *process, std::vector<uint32_t>& indexes) const
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch{
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const size_t num_symbols = GetNumSymbols();
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->Indent();
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size());
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->IndentMore();
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!indexes.empty())
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    {
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        std::vector<uint32_t>::const_iterator pos;
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        std::vector<uint32_t>::const_iterator end = indexes.end();
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        DumpSymbolHeader (s);
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        for (pos = indexes.begin(); pos != end; ++pos)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        {
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            uint32_t idx = *pos;
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            if (idx < num_symbols)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            {
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                s->Indent();
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                m_symbols[idx].Dump(s, process, idx);
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            }
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->IndentLess ();
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSymtab::DumpSymbolHeader (Stream *s)
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    s->Indent("               Debug symbol\n");
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    s->Indent("               |Synthetic symbol\n");
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->Indent("               ||Externally Visible\n");
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    s->Indent("               |||\n");
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    s->Indent("Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name\n");
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Symbol *
140a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSymtab::SymbolAtIndex(uint32_t idx)
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (idx < m_symbols.size())
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return &m_symbols[idx];
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return NULL;
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const Symbol *
149a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSymtab::SymbolAtIndex(uint32_t idx) const
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch{
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (idx < m_symbols.size())
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return &m_symbols[idx];
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//----------------------------------------------------------------------
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// InitNameIndexes
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch//----------------------------------------------------------------------
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid
160a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochSymtab::InitNameIndexes()
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Create the name index vector to be able to quickly search by name
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const size_t count = m_symbols.size();
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    assert(m_objfile != NULL);
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    assert(m_objfile->GetModule() != NULL);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    m_name_to_index.Reserve (count);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UniqueCStringMap<uint32_t>::Entry entry;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (entry.value = 0; entry.value < count; ++entry.value)
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    {
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        const Symbol *symbol = &m_symbols[entry.value];
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // Don't let trampolines get into the lookup by name map
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // If we ever need the trampoline symbols to be searchable by name
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // we can remove this and then possibly add a new bool to any of the
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // Symtab functions that lookup symbols by name to indicate if they
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        // want trampolines.
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (symbol->IsTrampoline())
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            continue;
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        const Mangled &mangled = symbol->GetMangled();
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        entry.cstring = mangled.GetMangledName().GetCString();
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        if (entry.cstring && entry.cstring[0])
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            m_name_to_index.Append (entry);
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        entry.cstring = mangled.GetDemangledName().GetCString();
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (entry.cstring && entry.cstring[0])
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            m_name_to_index.Append (entry);
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
192    m_name_to_index.Sort();
193}
194
195uint32_t
196Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
197{
198    uint32_t prev_size = indexes.size();
199
200    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
201
202    for (uint32_t i = start_idx; i < count; ++i)
203    {
204        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
205            indexes.push_back(i);
206    }
207
208    return indexes.size() - prev_size;
209}
210
211struct SymbolSortInfo
212{
213    const bool sort_by_load_addr;
214    const Symbol *symbols;
215};
216
217namespace {
218    struct SymbolIndexComparator {
219        const std::vector<Symbol>& symbols;
220        SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
221        bool operator()(uint32_t index_a, uint32_t index_b) {
222            addr_t value_a;
223            addr_t value_b;
224            if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
225                value_a = symbols[index_a].GetValue ().GetOffset();
226                value_b = symbols[index_b].GetValue ().GetOffset();
227            } else {
228                value_a = symbols[index_a].GetValue ().GetFileAddress();
229                value_b = symbols[index_b].GetValue ().GetFileAddress();
230            }
231
232            if (value_a == value_b) {
233                // The if the values are equal, use the original symbol user ID
234                lldb::user_id_t uid_a = symbols[index_a].GetID();
235                lldb::user_id_t uid_b = symbols[index_b].GetID();
236                if (uid_a < uid_b)
237                    return true;
238                if (uid_a > uid_b)
239                    return false;
240                return false;
241            } else if (value_a < value_b)
242                return true;
243
244            return false;
245        }
246    };
247}
248
249void
250Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
251{
252    Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
253    // No need to sort if we have zero or one items...
254    if (indexes.size() <= 1)
255        return;
256
257    // Sort the indexes in place using std::sort
258    std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
259
260    // Remove any duplicates if requested
261    if (remove_duplicates)
262        std::unique(indexes.begin(), indexes.end());
263}
264
265uint32_t
266Symtab::AppendSymbolIndexesWithName(const ConstString& symbol_name, std::vector<uint32_t>& indexes)
267{
268    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
269    if (symbol_name)
270    {
271        const size_t old_size = indexes.size();
272        if (m_name_to_index.IsEmpty())
273            InitNameIndexes();
274
275        const char *symbol_cstr = symbol_name.GetCString();
276        const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
277        for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
278             entry_ptr!= NULL;
279             entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
280        {
281            indexes.push_back (entry_ptr->value);
282        }
283        return indexes.size() - old_size;
284    }
285    return 0;
286}
287
288uint32_t
289Symtab::AppendSymbolIndexesWithNameAndType(const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
290{
291    if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
292    {
293        std::vector<uint32_t>::iterator pos = indexes.begin();
294        while (pos != indexes.end())
295        {
296            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
297                ++pos;
298            else
299                indexes.erase(pos);
300        }
301    }
302    return indexes.size();
303}
304
305uint32_t
306Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
307{
308    uint32_t prev_size = indexes.size();
309    uint32_t sym_end = m_symbols.size();
310
311    for (int i = 0; i < sym_end; i++)
312    {
313        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
314        {
315            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
316            if (name)
317            {
318                if (regexp.Execute (name))
319                    indexes.push_back(i);
320            }
321        }
322    }
323    return indexes.size() - prev_size;
324
325}
326
327Symbol *
328Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx)
329{
330    const size_t count = m_symbols.size();
331    for (uint32_t idx = start_idx; idx < count; ++idx)
332    {
333        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
334        {
335            start_idx = idx;
336            return &m_symbols[idx];
337        }
338    }
339    return NULL;
340}
341
342const Symbol *
343Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx) const
344{
345    const size_t count = m_symbols.size();
346    for (uint32_t idx = start_idx; idx < count; ++idx)
347    {
348        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
349        {
350            start_idx = idx;
351            return &m_symbols[idx];
352        }
353    }
354    return NULL;
355}
356
357size_t
358Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
359{
360    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
361    // Initialize all of the lookup by name indexes before converting NAME
362    // to a uniqued string NAME_STR below.
363    if (m_name_to_index.IsEmpty())
364        InitNameIndexes();
365
366    if (name)
367    {
368        // The string table did have a string that matched, but we need
369        // to check the symbols and match the symbol_type if any was given.
370        AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
371    }
372    return symbol_indexes.size();
373}
374
375size_t
376Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
377{
378    AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_indexes);
379    return symbol_indexes.size();
380}
381
382Symbol *
383Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
384{
385    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
386    if (m_name_to_index.IsEmpty())
387        InitNameIndexes();
388
389    if (name)
390    {
391        std::vector<uint32_t> matching_indexes;
392        // The string table did have a string that matched, but we need
393        // to check the symbols and match the symbol_type if any was given.
394        if (AppendSymbolIndexesWithNameAndType(name, symbol_type, matching_indexes))
395        {
396            std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
397            for (pos = matching_indexes.begin(); pos != end; ++pos)
398            {
399                Symbol *symbol = SymbolAtIndex(*pos);
400
401                if (symbol->Compare(name, symbol_type))
402                    return symbol;
403            }
404        }
405    }
406    return NULL;
407}
408
409typedef struct
410{
411    const Symtab *symtab;
412    const addr_t file_addr;
413    Symbol *match_symbol;
414    const uint32_t *match_index_ptr;
415    addr_t match_offset;
416} SymbolSearchInfo;
417
418static int
419SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
420{
421    const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
422    if (curr_symbol == NULL)
423        return -1;
424
425    const addr_t info_file_addr = info->file_addr;
426
427    // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
428    // range if the symbol has a section!
429    const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
430    if (curr_range)
431    {
432        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
433        if (info_file_addr < curr_file_addr)
434            return -1;
435        if (info_file_addr > curr_file_addr)
436            return +1;
437        info->match_symbol = const_cast<Symbol *>(curr_symbol);
438        info->match_index_ptr = index_ptr;
439        return 0;
440    }
441
442    return -1;
443}
444
445static int
446SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
447{
448    const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
449    if (symbol == NULL)
450        return -1;
451
452    const addr_t info_file_addr = info->file_addr;
453    const AddressRange *curr_range = symbol->GetAddressRangePtr();
454    if (curr_range)
455    {
456        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
457        if (info_file_addr < curr_file_addr)
458            return -1;
459
460        // Since we are finding the closest symbol that is greater than or equal
461        // to 'info->file_addr' we set the symbol here. This will get set
462        // multiple times, but after the search is done it will contain the best
463        // symbol match
464        info->match_symbol = const_cast<Symbol *>(symbol);
465        info->match_index_ptr = index_ptr;
466        info->match_offset = info_file_addr - curr_file_addr;
467
468        if (info_file_addr > curr_file_addr)
469            return +1;
470        return 0;
471    }
472    return -1;
473}
474
475static SymbolSearchInfo
476FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
477{
478    SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
479    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
480    return info;
481}
482
483
484void
485Symtab::InitAddressIndexes()
486{
487    if (m_addr_indexes.empty())
488    {
489        AppendSymbolIndexesWithType (eSymbolTypeFunction, m_addr_indexes);
490        AppendSymbolIndexesWithType (eSymbolTypeGlobal, m_addr_indexes);
491        AppendSymbolIndexesWithType (eSymbolTypeStatic, m_addr_indexes);
492        AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
493        AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
494        AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
495        SortSymbolIndexesByValue(m_addr_indexes, true);
496        m_addr_indexes.push_back(UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
497    }
498}
499
500size_t
501Symtab::CalculateSymbolSize (Symbol *symbol)
502{
503    // Make sure this symbol is from this symbol table...
504    if (symbol < m_symbols.data() && symbol >= m_symbols.data() + m_symbols.size())
505        return 0;
506
507    // See if this symbol already has a byte size?
508    size_t byte_size = symbol->GetByteSize();
509
510    if (byte_size)
511    {
512        // It does, just return it
513        return byte_size;
514    }
515
516    // Else if this is an address based symbol, figure out the delta between
517    // it and the next address based symbol
518    if (symbol->GetAddressRangePtr())
519    {
520        if (m_addr_indexes.empty())
521            InitAddressIndexes();
522        const size_t num_addr_indexes = m_addr_indexes.size();
523        SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), m_addr_indexes.data(), num_addr_indexes);
524        if (info.match_index_ptr != NULL)
525        {
526            const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
527            // We can figure out the address range of all symbols except the
528            // last one by taking the delta between the current symbol and
529            // the next symbol
530
531            for (uint32_t addr_index = info.match_index_ptr - m_addr_indexes.data() + 1;
532                 addr_index < num_addr_indexes;
533                 ++addr_index)
534            {
535                Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
536                if (next_symbol == NULL)
537                    break;
538
539                assert (next_symbol->GetAddressRangePtr());
540                const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
541                if (next_file_addr > curr_file_addr)
542                {
543                    byte_size = next_file_addr - curr_file_addr;
544                    symbol->GetAddressRangePtr()->SetByteSize(byte_size);
545                    symbol->SetSizeIsSynthesized(true);
546                    break;
547                }
548            }
549        }
550    }
551    return byte_size;
552}
553
554Symbol *
555Symtab::FindSymbolWithFileAddress (addr_t file_addr)
556{
557    if (m_addr_indexes.empty())
558        InitAddressIndexes();
559
560    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
561
562    uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress);
563    if (match)
564        return SymbolAtIndex (*match);
565    return NULL;
566}
567
568
569Symbol *
570Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
571{
572    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
573
574    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
575
576    if (info.match_symbol)
577    {
578        if (info.match_offset < CalculateSymbolSize(info.match_symbol))
579            return info.match_symbol;
580    }
581    return NULL;
582}
583
584Symbol *
585Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
586{
587    if (m_addr_indexes.empty())
588        InitAddressIndexes();
589
590    return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
591}
592
593