Symtab.cpp revision 7e5fa7fc1f8efd24c078e063b2c4b5e13ba5be20
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Core/Module.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Core/RegularExpression.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Core/Timer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Symbol/ObjectFile.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Symbol/Symtab.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "lldb/Target/ObjCLanguageRuntime.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace lldb;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace lldb_private;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::Symtab(ObjectFile *objfile) :
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_objfile (objfile),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_symbols (),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_addr_indexes (),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_name_to_index (),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_mutex (Mutex::eMutexTypeRecursive),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_addr_indexes_computed (false),
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    m_name_indexes_computed (false)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::~Symtab()
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::Reserve(uint32_t count)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clients should grab the mutex from this symbol table and lock it manually
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when calling this function to avoid performance issues.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_symbols.reserve (count);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol *
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::Resize(uint32_t count)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clients should grab the mutex from this symbol table and lock it manually
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when calling this function to avoid performance issues.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_symbols.resize (count);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &m_symbols[0];
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Symtab::AddSymbol(const Symbol& symbol)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clients should grab the mutex from this symbol table and lock it manually
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when calling this function to avoid performance issues.
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    uint32_t symbol_idx = m_symbols.size();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_name_to_index.Clear();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_addr_indexes.clear();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_symbols.push_back(symbol);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    m_addr_indexes_computed = false;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m_name_indexes_computed = false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return symbol_idx;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::GetNumSymbols() const
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return m_symbols.size();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Mutex::Locker locker (m_mutex);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileSpec &file_spec = m_objfile->GetFileSpec();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char * object_name = NULL;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (m_objfile->GetModule())
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        object_name = m_objfile->GetModule()->GetObjectName().GetCString();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_spec)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %lu",
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_spec.GetDirectory().AsCString(),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_spec.GetFilename().AsCString(),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        object_name ? "(" : "",
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        object_name ? object_name : "",
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        object_name ? ")" : "",
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_symbols.size());
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s->Printf("Symtab, num_symbols = %lu", m_symbols.size());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!m_symbols.empty())
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switch (sort_order)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case eSortOrderNone:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                s->PutCString (":\n");
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                DumpSymbolHeader (s);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const_iterator begin = m_symbols.begin();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const_iterator end = m_symbols.end();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    s->Indent();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    pos->Dump(s, target, std::distance(begin, pos));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case eSortOrderByName:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // Although we maintain a lookup by exact name map, the table
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // isn't sorted by name. So we must make the ordered symbol list
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // up ourselves.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                s->PutCString (" (sorted by name):\n");
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                DumpSymbolHeader (s);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                CStringToSymbol name_map;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (name && name[0])
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        name_map.insert (std::make_pair(name, &(*pos)));
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                }
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    s->Indent();
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    pos->second->Dump (s, target, pos->second - &m_symbols[0]);
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                }
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            }
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case eSortOrderByAddress:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s->PutCString (" (sorted by address):\n");
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DumpSymbolHeader (s);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!m_addr_indexes_computed)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                InitAddressIndexes();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const size_t num_symbols = GetNumSymbols();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::vector<uint32_t>::const_iterator pos;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::vector<uint32_t>::const_iterator end = m_addr_indexes.end();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (pos = m_addr_indexes.begin(); pos != end; ++pos)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                uint32_t idx = *pos;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (idx < num_symbols)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    s->Indent();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    m_symbols[idx].Dump(s, target, idx);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t num_symbols = GetNumSymbols();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Printf("Symtab %lu symbol indexes (%lu symbols total):\n", indexes.size(), m_symbols.size());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->IndentMore();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!indexes.empty())
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::vector<uint32_t>::const_iterator pos;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::vector<uint32_t>::const_iterator end = indexes.end();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DumpSymbolHeader (s);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (pos = indexes.begin(); pos != end; ++pos)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            uint32_t idx = *pos;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (idx < num_symbols)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                s->Indent();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                m_symbols[idx].Dump(s, target, idx);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->IndentLess ();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::DumpSymbolHeader (Stream *s)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("               Debug symbol\n");
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("               |Synthetic symbol\n");
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("               ||Externally Visible\n");
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("               |||\n");
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name\n");
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CompareSymbolID (const void *key, const void *p)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const user_id_t match_uid = *(user_id_t*) key;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const user_id_t symbol_uid = ((Symbol *)p)->GetID();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (match_uid < symbol_uid)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return -1;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (match_uid > symbol_uid)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol *
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &m_symbols[0],
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         m_symbols.size(),
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0],
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         CompareSymbolID);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return symbol;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symbol *
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::SymbolAtIndex(uint32_t idx)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clients should grab the mutex from this symbol table and lock it manually
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when calling this function to avoid performance issues.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (idx < m_symbols.size())
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return &m_symbols[idx];
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Symbol *
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::SymbolAtIndex(uint32_t idx) const
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clients should grab the mutex from this symbol table and lock it manually
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when calling this function to avoid performance issues.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (idx < m_symbols.size())
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return &m_symbols[idx];
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitNameIndexes
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::InitNameIndexes()
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Protected function, no need to lock mutex...
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!m_name_indexes_computed)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_name_indexes_computed = true;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Create the name index vector to be able to quickly search by name
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const size_t count = m_symbols.size();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert(m_objfile != NULL);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert(m_objfile->GetModule() != NULL);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 1
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_name_to_index.Reserve (count);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO: benchmark this to see if we save any memory. Otherwise we
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // will always keep the memory reserved in the vector unless we pull
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // some STL swap magic and then recopy...
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t actual_count = 0;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             pos != end;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ++pos)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const Mangled &mangled = pos->GetMangled();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mangled.GetMangledName())
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ++actual_count;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mangled.GetDemangledName())
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ++actual_count;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_name_to_index.Reserve (actual_count);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UniqueCStringMap<uint32_t>::Entry entry;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (entry.value = 0; entry.value < count; ++entry.value)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const Symbol *symbol = &m_symbols[entry.value];
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Don't let trampolines get into the lookup by name map
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // If we ever need the trampoline symbols to be searchable by name
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // we can remove this and then possibly add a new bool to any of the
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // Symtab functions that lookup symbols by name to indicate if they
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // want trampolines.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (symbol->IsTrampoline())
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const Mangled &mangled = symbol->GetMangled();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry.cstring = mangled.GetMangledName().GetCString();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (entry.cstring && entry.cstring[0])
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                m_name_to_index.Append (entry);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            entry.cstring = mangled.GetDemangledName().GetCString();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (entry.cstring && entry.cstring[0])
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                m_name_to_index.Append (entry);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // If the demangled name turns out to be an ObjC name, and
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // is a category name, add the version without categories to the index too.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ConstString objc_base_name;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (ObjCLanguageRuntime::ParseMethodName (entry.cstring,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      NULL,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      NULL,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      &objc_base_name)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                && !objc_base_name.IsEmpty())
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                entry.cstring = objc_base_name.GetCString();
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                m_name_to_index.Append (entry);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        m_name_to_index.Sort();
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t prev_size = indexes.size();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t i = start_idx; i < count; ++i)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            indexes.push_back(i);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return indexes.size() - prev_size;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t prev_size = indexes.size();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t i = start_idx; i < count; ++i)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            indexes.push_back(i);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return indexes.size() - prev_size;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t prev_size = indexes.size();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (uint32_t i = start_idx; i < count; ++i)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                indexes.push_back(i);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return indexes.size() - prev_size;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::GetIndexForSymbol (const Symbol *symbol) const
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Symbol *first_symbol = &m_symbols[0];
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return symbol - first_symbol;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UINT32_MAX;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct SymbolSortInfo
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool sort_by_load_addr;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Symbol *symbols;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct SymbolIndexComparator {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::vector<Symbol>& symbols;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool operator()(uint32_t index_a, uint32_t index_b) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            addr_t value_a;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            addr_t value_b;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                value_a = symbols[index_a].GetValue ().GetOffset();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                value_b = symbols[index_b].GetValue ().GetOffset();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                value_a = symbols[index_a].GetValue ().GetFileAddress();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                value_b = symbols[index_b].GetValue ().GetFileAddress();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (value_a == value_b) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // The if the values are equal, use the original symbol user ID
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                lldb::user_id_t uid_a = symbols[index_a].GetID();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                lldb::user_id_t uid_b = symbols[index_b].GetID();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (uid_a < uid_b)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    return true;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (uid_a > uid_b)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    return false;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return false;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else if (value_a < value_b)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return true;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need to sort if we have zero or one items...
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (indexes.size() <= 1)
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sort the indexes in place using std::stable_sort.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not correctness.  The indexes vector tends to be "close" to sorted, which the
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // stable sort handles better.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove any duplicates if requested
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (remove_duplicates)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::unique(indexes.begin(), indexes.end());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (symbol_name)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char *symbol_cstr = symbol_name.GetCString();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!m_name_indexes_computed)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            InitNameIndexes();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return m_name_to_index.GetValues (symbol_cstr, indexes);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Locker locker (m_mutex);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (symbol_name)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
482        const size_t old_size = indexes.size();
483        if (!m_name_indexes_computed)
484            InitNameIndexes();
485
486        const char *symbol_cstr = symbol_name.GetCString();
487
488        std::vector<uint32_t> all_name_indexes;
489        const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
490        for (size_t i=0; i<name_match_count; ++i)
491        {
492            if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
493                indexes.push_back (all_name_indexes[i]);
494        }
495        return indexes.size() - old_size;
496    }
497    return 0;
498}
499
500uint32_t
501Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
502{
503    Mutex::Locker locker (m_mutex);
504
505    if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
506    {
507        std::vector<uint32_t>::iterator pos = indexes.begin();
508        while (pos != indexes.end())
509        {
510            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
511                ++pos;
512            else
513                indexes.erase(pos);
514        }
515    }
516    return indexes.size();
517}
518
519uint32_t
520Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
521{
522    Mutex::Locker locker (m_mutex);
523
524    if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
525    {
526        std::vector<uint32_t>::iterator pos = indexes.begin();
527        while (pos != indexes.end())
528        {
529            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
530                ++pos;
531            else
532                indexes.erase(pos);
533        }
534    }
535    return indexes.size();
536}
537
538
539uint32_t
540Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
541{
542    Mutex::Locker locker (m_mutex);
543
544    uint32_t prev_size = indexes.size();
545    uint32_t sym_end = m_symbols.size();
546
547    for (int i = 0; i < sym_end; i++)
548    {
549        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
550        {
551            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
552            if (name)
553            {
554                if (regexp.Execute (name))
555                    indexes.push_back(i);
556            }
557        }
558    }
559    return indexes.size() - prev_size;
560
561}
562
563uint32_t
564Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
565{
566    Mutex::Locker locker (m_mutex);
567
568    uint32_t prev_size = indexes.size();
569    uint32_t sym_end = m_symbols.size();
570
571    for (int i = 0; i < sym_end; i++)
572    {
573        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
574        {
575            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
576                continue;
577
578            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
579            if (name)
580            {
581                if (regexp.Execute (name))
582                    indexes.push_back(i);
583            }
584        }
585    }
586    return indexes.size() - prev_size;
587
588}
589
590Symbol *
591Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
592{
593    Mutex::Locker locker (m_mutex);
594
595    const size_t count = m_symbols.size();
596    for (uint32_t idx = start_idx; idx < count; ++idx)
597    {
598        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
599        {
600            if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
601            {
602                start_idx = idx;
603                return &m_symbols[idx];
604            }
605        }
606    }
607    return NULL;
608}
609
610size_t
611Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
612{
613    Mutex::Locker locker (m_mutex);
614
615    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
616    // Initialize all of the lookup by name indexes before converting NAME
617    // to a uniqued string NAME_STR below.
618    if (!m_name_indexes_computed)
619        InitNameIndexes();
620
621    if (name)
622    {
623        // The string table did have a string that matched, but we need
624        // to check the symbols and match the symbol_type if any was given.
625        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
626    }
627    return symbol_indexes.size();
628}
629
630size_t
631Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
632{
633    Mutex::Locker locker (m_mutex);
634
635    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
636    // Initialize all of the lookup by name indexes before converting NAME
637    // to a uniqued string NAME_STR below.
638    if (!m_name_indexes_computed)
639        InitNameIndexes();
640
641    if (name)
642    {
643        // The string table did have a string that matched, but we need
644        // to check the symbols and match the symbol_type if any was given.
645        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
646    }
647    return symbol_indexes.size();
648}
649
650size_t
651Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
652{
653    Mutex::Locker locker (m_mutex);
654
655    AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
656    return symbol_indexes.size();
657}
658
659Symbol *
660Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
661{
662    Mutex::Locker locker (m_mutex);
663
664    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
665    if (!m_name_indexes_computed)
666        InitNameIndexes();
667
668    if (name)
669    {
670        std::vector<uint32_t> matching_indexes;
671        // The string table did have a string that matched, but we need
672        // to check the symbols and match the symbol_type if any was given.
673        if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
674        {
675            std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
676            for (pos = matching_indexes.begin(); pos != end; ++pos)
677            {
678                Symbol *symbol = SymbolAtIndex(*pos);
679
680                if (symbol->Compare(name, symbol_type))
681                    return symbol;
682            }
683        }
684    }
685    return NULL;
686}
687
688typedef struct
689{
690    const Symtab *symtab;
691    const addr_t file_addr;
692    Symbol *match_symbol;
693    const uint32_t *match_index_ptr;
694    addr_t match_offset;
695} SymbolSearchInfo;
696
697static int
698SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
699{
700    const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
701    if (curr_symbol == NULL)
702        return -1;
703
704    const addr_t info_file_addr = info->file_addr;
705
706    // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
707    // range if the symbol has a section!
708    const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
709    if (curr_range)
710    {
711        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
712        if (info_file_addr < curr_file_addr)
713            return -1;
714        if (info_file_addr > curr_file_addr)
715            return +1;
716        info->match_symbol = const_cast<Symbol *>(curr_symbol);
717        info->match_index_ptr = index_ptr;
718        return 0;
719    }
720
721    return -1;
722}
723
724static int
725SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
726{
727    const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
728    if (symbol == NULL)
729        return -1;
730
731    const addr_t info_file_addr = info->file_addr;
732    const AddressRange *curr_range = symbol->GetAddressRangePtr();
733    if (curr_range)
734    {
735        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
736        if (info_file_addr < curr_file_addr)
737            return -1;
738
739        // Since we are finding the closest symbol that is greater than or equal
740        // to 'info->file_addr' we set the symbol here. This will get set
741        // multiple times, but after the search is done it will contain the best
742        // symbol match
743        info->match_symbol = const_cast<Symbol *>(symbol);
744        info->match_index_ptr = index_ptr;
745        info->match_offset = info_file_addr - curr_file_addr;
746
747        if (info_file_addr > curr_file_addr)
748            return +1;
749        return 0;
750    }
751    return -1;
752}
753
754static SymbolSearchInfo
755FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
756{
757    SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
758    ::bsearch (&info,
759               indexes,
760               num_indexes,
761               sizeof(uint32_t),
762               (ComparisonFunction)SymbolWithClosestFileAddress);
763    return info;
764}
765
766
767void
768Symtab::InitAddressIndexes()
769{
770    // Protected function, no need to lock mutex...
771    if (!m_addr_indexes_computed && !m_symbols.empty())
772    {
773        m_addr_indexes_computed = true;
774#if 0
775        // The old was to add only code, trampoline or data symbols...
776        AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
777        AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
778        AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
779#else
780        // The new way adds all symbols with valid addresses that are section
781        // offset.
782        const_iterator begin = m_symbols.begin();
783        const_iterator end = m_symbols.end();
784        for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
785        {
786            if (pos->GetAddressRangePtr())
787                m_addr_indexes.push_back (std::distance(begin, pos));
788        }
789#endif
790        SortSymbolIndexesByValue (m_addr_indexes, false);
791        m_addr_indexes.push_back (UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
792    }
793}
794
795size_t
796Symtab::CalculateSymbolSize (Symbol *symbol)
797{
798    Mutex::Locker locker (m_mutex);
799
800    if (m_symbols.empty())
801        return 0;
802
803    // Make sure this symbol is from this symbol table...
804    if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
805        return 0;
806
807    // See if this symbol already has a byte size?
808    size_t byte_size = symbol->GetByteSize();
809
810    if (byte_size)
811    {
812        // It does, just return it
813        return byte_size;
814    }
815
816    // Else if this is an address based symbol, figure out the delta between
817    // it and the next address based symbol
818    if (symbol->GetAddressRangePtr())
819    {
820        if (!m_addr_indexes_computed)
821            InitAddressIndexes();
822        const size_t num_addr_indexes = m_addr_indexes.size();
823        SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
824        if (info.match_index_ptr != NULL)
825        {
826            const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
827            // We can figure out the address range of all symbols except the
828            // last one by taking the delta between the current symbol and
829            // the next symbol
830
831            for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
832                 addr_index < num_addr_indexes;
833                 ++addr_index)
834            {
835                Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
836                if (next_symbol == NULL)
837                    break;
838
839                assert (next_symbol->GetAddressRangePtr());
840                const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
841                if (next_file_addr > curr_file_addr)
842                {
843                    byte_size = next_file_addr - curr_file_addr;
844                    symbol->GetAddressRangePtr()->SetByteSize(byte_size);
845                    symbol->SetSizeIsSynthesized(true);
846                    break;
847                }
848            }
849        }
850    }
851    return byte_size;
852}
853
854Symbol *
855Symtab::FindSymbolWithFileAddress (addr_t file_addr)
856{
857    Mutex::Locker locker (m_mutex);
858
859    if (!m_addr_indexes_computed)
860        InitAddressIndexes();
861
862    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
863
864    uint32_t* match = (uint32_t*)::bsearch (&info,
865                                            &m_addr_indexes[0],
866                                            m_addr_indexes.size(),
867                                            sizeof(uint32_t),
868                                            (ComparisonFunction)SymbolWithFileAddress);
869    if (match)
870        return SymbolAtIndex (*match);
871    return NULL;
872}
873
874
875Symbol *
876Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
877{
878    Mutex::Locker locker (m_mutex);
879
880    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
881
882    ::bsearch (&info,
883               indexes,
884               num_indexes,
885               sizeof(uint32_t),
886               (ComparisonFunction)SymbolWithClosestFileAddress);
887
888    if (info.match_symbol)
889    {
890        if (info.match_offset == 0)
891        {
892            // We found an exact match!
893            return info.match_symbol;
894        }
895
896        const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol);
897
898        if (symbol_byte_size == 0)
899        {
900            // We weren't able to find the size of the symbol so lets just go
901            // with that match we found in our search...
902            return info.match_symbol;
903        }
904
905        // We were able to figure out a symbol size so lets make sure our
906        // offset puts "file_addr" in the symbol's address range.
907        if (info.match_offset < symbol_byte_size)
908            return info.match_symbol;
909    }
910    return NULL;
911}
912
913Symbol *
914Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
915{
916    Mutex::Locker locker (m_mutex);
917
918    if (!m_addr_indexes_computed)
919        InitAddressIndexes();
920
921    return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
922}
923
924