1254721Semaste//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "DWARFDebugPubnamesSet.h"
11254721Semaste
12254721Semaste#include "lldb/Core/RegularExpression.h"
13254721Semaste#include "lldb/Core/Log.h"
14254721Semaste
15254721Semaste#include "SymbolFileDWARF.h"
16254721Semaste
17254721Semasteusing namespace lldb_private;
18254721Semaste
19254721SemasteDWARFDebugPubnamesSet::DWARFDebugPubnamesSet() :
20254721Semaste    m_offset(DW_INVALID_OFFSET),
21254721Semaste    m_header(),
22254721Semaste    m_descriptors(),
23254721Semaste    m_name_to_descriptor_index()
24254721Semaste{
25254721Semaste}
26254721Semaste
27254721SemasteDWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t cu_die_length) :
28254721Semaste    m_offset(debug_aranges_offset),
29254721Semaste    m_header(),
30254721Semaste    m_descriptors(),
31254721Semaste    m_name_to_descriptor_index()
32254721Semaste{
33254721Semaste    m_header.length = 10;               // set the length to only include the header right for now
34254721Semaste    m_header.version = 2;               // The DWARF version number
35254721Semaste    m_header.die_offset = cu_die_offset;// compile unit .debug_info offset
36254721Semaste    m_header.die_length = cu_die_length;// compile unit .debug_info length
37254721Semaste}
38254721Semaste
39254721Semastevoid
40254721SemasteDWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset, const char* name)
41254721Semaste{
42254721Semaste    if (name && name[0])
43254721Semaste    {
44254721Semaste        // Adjust our header length
45254721Semaste        m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
46254721Semaste        Descriptor pubnameDesc(cu_rel_offset, name);
47254721Semaste        m_descriptors.push_back(pubnameDesc);
48254721Semaste    }
49254721Semaste}
50254721Semaste
51254721Semastevoid
52254721SemasteDWARFDebugPubnamesSet::Clear()
53254721Semaste{
54254721Semaste    m_offset = DW_INVALID_OFFSET;
55254721Semaste    m_header.length = 10;
56254721Semaste    m_header.version = 2;
57254721Semaste    m_header.die_offset = DW_INVALID_OFFSET;
58254721Semaste    m_header.die_length = 0;
59254721Semaste    m_descriptors.clear();
60254721Semaste}
61254721Semaste
62254721Semaste
63254721Semaste//----------------------------------------------------------------------
64254721Semaste// InitNameIndexes
65254721Semaste//----------------------------------------------------------------------
66254721Semastevoid
67254721SemasteDWARFDebugPubnamesSet::InitNameIndexes() const
68254721Semaste{
69254721Semaste    // Create the name index vector to be able to quickly search by name
70254721Semaste    const size_t count = m_descriptors.size();
71254721Semaste    for (uint32_t idx = 0; idx < count; ++idx)
72254721Semaste    {
73254721Semaste        const char* name = m_descriptors[idx].name.c_str();
74254721Semaste        if (name && name[0])
75254721Semaste            m_name_to_descriptor_index.insert(cstr_to_index_mmap::value_type(name, idx));
76254721Semaste    }
77254721Semaste}
78254721Semaste
79254721Semaste
80254721Semastebool
81258054SemasteDWARFDebugPubnamesSet::Extract(const DWARFDataExtractor& data, lldb::offset_t *offset_ptr)
82254721Semaste{
83254721Semaste    if (data.ValidOffset(*offset_ptr))
84254721Semaste    {
85254721Semaste        m_descriptors.clear();
86254721Semaste        m_offset = *offset_ptr;
87258054Semaste        m_header.length     = data.GetDWARFInitialLength(offset_ptr);
88254721Semaste        m_header.version    = data.GetU16(offset_ptr);
89258054Semaste        m_header.die_offset = data.GetDWARFOffset(offset_ptr);
90258054Semaste        m_header.die_length = data.GetDWARFOffset(offset_ptr);
91254721Semaste
92254721Semaste        Descriptor pubnameDesc;
93254721Semaste        while (data.ValidOffset(*offset_ptr))
94254721Semaste        {
95258054Semaste            pubnameDesc.offset  = data.GetDWARFOffset(offset_ptr);
96254721Semaste
97254721Semaste            if (pubnameDesc.offset)
98254721Semaste            {
99254721Semaste                const char* name = data.GetCStr(offset_ptr);
100254721Semaste                if (name && name[0])
101254721Semaste                {
102254721Semaste                    pubnameDesc.name = name;
103254721Semaste                    m_descriptors.push_back(pubnameDesc);
104254721Semaste                }
105254721Semaste            }
106254721Semaste            else
107254721Semaste                break;  // We are done if we get a zero 4 byte offset
108254721Semaste        }
109254721Semaste
110254721Semaste        return !m_descriptors.empty();
111254721Semaste    }
112254721Semaste    return false;
113254721Semaste}
114254721Semaste
115254721Semastedw_offset_t
116254721SemasteDWARFDebugPubnamesSet::GetOffsetOfNextEntry() const
117254721Semaste{
118254721Semaste    return m_offset + m_header.length + 4;
119254721Semaste}
120254721Semaste
121254721Semastevoid
122254721SemasteDWARFDebugPubnamesSet::Dump(Log *log) const
123254721Semaste{
124254721Semaste    log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, die_offset = 0x%8.8x, die_length = 0x%8.8x",
125254721Semaste        m_header.length,
126254721Semaste        m_header.version,
127254721Semaste        m_header.die_offset,
128254721Semaste        m_header.die_length);
129254721Semaste
130254721Semaste    bool verbose = log->GetVerbose();
131254721Semaste
132254721Semaste    DescriptorConstIter pos;
133254721Semaste    DescriptorConstIter end = m_descriptors.end();
134254721Semaste    for (pos = m_descriptors.begin(); pos != end; ++pos)
135254721Semaste    {
136254721Semaste        if (verbose)
137254721Semaste            log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset, m_header.die_offset, pos->offset + m_header.die_offset, pos->name.c_str());
138254721Semaste        else
139254721Semaste            log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset, pos->name.c_str());
140254721Semaste    }
141254721Semaste}
142254721Semaste
143254721Semaste
144254721Semastevoid
145254721SemasteDWARFDebugPubnamesSet::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const
146254721Semaste{
147254721Semaste    if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
148254721Semaste        InitNameIndexes();
149254721Semaste
150254721Semaste    std::pair<cstr_to_index_mmap::const_iterator, cstr_to_index_mmap::const_iterator> range(m_name_to_descriptor_index.equal_range(name));
151254721Semaste    for (cstr_to_index_mmap::const_iterator pos = range.first; pos != range.second; ++pos)
152254721Semaste        die_offset_coll.push_back(m_header.die_offset + m_descriptors[(*pos).second].offset);
153254721Semaste}
154254721Semaste
155254721Semastevoid
156254721SemasteDWARFDebugPubnamesSet::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offset_coll) const
157254721Semaste{
158254721Semaste    DescriptorConstIter pos;
159254721Semaste    DescriptorConstIter end = m_descriptors.end();
160254721Semaste    for (pos = m_descriptors.begin(); pos != end; ++pos)
161254721Semaste    {
162254721Semaste        if ( regex.Execute(pos->name.c_str()) )
163254721Semaste            die_offset_coll.push_back(m_header.die_offset + pos->offset);
164254721Semaste    }
165254721Semaste}
166254721Semaste
167