1//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DWARFDebugPubnamesSet.h"
11
12#include "lldb/Core/RegularExpression.h"
13#include "lldb/Core/Log.h"
14
15#include "SymbolFileDWARF.h"
16
17using namespace lldb_private;
18
19DWARFDebugPubnamesSet::DWARFDebugPubnamesSet() :
20    m_offset(DW_INVALID_OFFSET),
21    m_header(),
22    m_descriptors(),
23    m_name_to_descriptor_index()
24{
25}
26
27DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t cu_die_length) :
28    m_offset(debug_aranges_offset),
29    m_header(),
30    m_descriptors(),
31    m_name_to_descriptor_index()
32{
33    m_header.length = 10;               // set the length to only include the header right for now
34    m_header.version = 2;               // The DWARF version number
35    m_header.die_offset = cu_die_offset;// compile unit .debug_info offset
36    m_header.die_length = cu_die_length;// compile unit .debug_info length
37}
38
39void
40DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset, const char* name)
41{
42    if (name && name[0])
43    {
44        // Adjust our header length
45        m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
46        Descriptor pubnameDesc(cu_rel_offset, name);
47        m_descriptors.push_back(pubnameDesc);
48    }
49}
50
51void
52DWARFDebugPubnamesSet::Clear()
53{
54    m_offset = DW_INVALID_OFFSET;
55    m_header.length = 10;
56    m_header.version = 2;
57    m_header.die_offset = DW_INVALID_OFFSET;
58    m_header.die_length = 0;
59    m_descriptors.clear();
60}
61
62
63//----------------------------------------------------------------------
64// InitNameIndexes
65//----------------------------------------------------------------------
66void
67DWARFDebugPubnamesSet::InitNameIndexes() const
68{
69    // Create the name index vector to be able to quickly search by name
70    const size_t count = m_descriptors.size();
71    for (uint32_t idx = 0; idx < count; ++idx)
72    {
73        const char* name = m_descriptors[idx].name.c_str();
74        if (name && name[0])
75            m_name_to_descriptor_index.insert(cstr_to_index_mmap::value_type(name, idx));
76    }
77}
78
79
80bool
81DWARFDebugPubnamesSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
82{
83    if (data.ValidOffset(*offset_ptr))
84    {
85        m_descriptors.clear();
86        m_offset = *offset_ptr;
87        m_header.length     = data.GetU32(offset_ptr);
88        m_header.version    = data.GetU16(offset_ptr);
89        m_header.die_offset = data.GetU32(offset_ptr);
90        m_header.die_length = data.GetU32(offset_ptr);
91
92        Descriptor pubnameDesc;
93        while (data.ValidOffset(*offset_ptr))
94        {
95            pubnameDesc.offset  = data.GetU32(offset_ptr);
96
97            if (pubnameDesc.offset)
98            {
99                const char* name = data.GetCStr(offset_ptr);
100                if (name && name[0])
101                {
102                    pubnameDesc.name = name;
103                    m_descriptors.push_back(pubnameDesc);
104                }
105            }
106            else
107                break;  // We are done if we get a zero 4 byte offset
108        }
109
110        return !m_descriptors.empty();
111    }
112    return false;
113}
114
115dw_offset_t
116DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const
117{
118    return m_offset + m_header.length + 4;
119}
120
121void
122DWARFDebugPubnamesSet::Dump(Log *log) const
123{
124    log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, die_offset = 0x%8.8x, die_length = 0x%8.8x",
125        m_header.length,
126        m_header.version,
127        m_header.die_offset,
128        m_header.die_length);
129
130    bool verbose = log->GetVerbose();
131
132    DescriptorConstIter pos;
133    DescriptorConstIter end = m_descriptors.end();
134    for (pos = m_descriptors.begin(); pos != end; ++pos)
135    {
136        if (verbose)
137            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());
138        else
139            log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset, pos->name.c_str());
140    }
141}
142
143
144void
145DWARFDebugPubnamesSet::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const
146{
147    if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
148        InitNameIndexes();
149
150    std::pair<cstr_to_index_mmap::const_iterator, cstr_to_index_mmap::const_iterator> range(m_name_to_descriptor_index.equal_range(name));
151    for (cstr_to_index_mmap::const_iterator pos = range.first; pos != range.second; ++pos)
152        die_offset_coll.push_back(m_header.die_offset + m_descriptors[(*pos).second].offset);
153}
154
155void
156DWARFDebugPubnamesSet::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offset_coll) const
157{
158    DescriptorConstIter pos;
159    DescriptorConstIter end = m_descriptors.end();
160    for (pos = m_descriptors.begin(); pos != end; ++pos)
161    {
162        if ( regex.Execute(pos->name.c_str()) )
163            die_offset_coll.push_back(m_header.die_offset + pos->offset);
164    }
165}
166
167