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 
17 using namespace lldb_private;
18 
DWARFDebugPubnamesSet()19 DWARFDebugPubnamesSet::DWARFDebugPubnamesSet() :
20     m_offset(DW_INVALID_OFFSET),
21     m_header(),
22     m_descriptors(),
23     m_name_to_descriptor_index()
24 {
25 }
26 
DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,dw_offset_t cu_die_offset,dw_offset_t cu_die_length)27 DWARFDebugPubnamesSet::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 
39 void
AddDescriptor(dw_offset_t cu_rel_offset,const char * name)40 DWARFDebugPubnamesSet::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 
51 void
Clear()52 DWARFDebugPubnamesSet::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 //----------------------------------------------------------------------
66 void
InitNameIndexes() const67 DWARFDebugPubnamesSet::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 
80 bool
Extract(const DataExtractor & data,lldb::offset_t * offset_ptr)81 DWARFDebugPubnamesSet::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 
115 dw_offset_t
GetOffsetOfNextEntry() const116 DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const
117 {
118     return m_offset + m_header.length + 4;
119 }
120 
121 void
Dump(Log * log) const122 DWARFDebugPubnamesSet::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 
144 void
Find(const char * name,bool ignore_case,std::vector<dw_offset_t> & die_offset_coll) const145 DWARFDebugPubnamesSet::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 
155 void
Find(const RegularExpression & regex,std::vector<dw_offset_t> & die_offset_coll) const156 DWARFDebugPubnamesSet::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