1 //===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "DWARFDebugPubnames.h"
12 #include "lldb/Core/Stream.h"
13 #include "lldb/Core/Timer.h"
15 #include "DWARFDebugInfo.h"
16 #include "DWARFDIECollection.h"
17 #include "DWARFFormValue.h"
18 #include "DWARFCompileUnit.h"
19 #include "LogChannelDWARF.h"
20 #include "SymbolFileDWARF.h"
24 using namespace lldb_private;
26 DWARFDebugPubnames::DWARFDebugPubnames() :
32 DWARFDebugPubnames::Extract(const DWARFDataExtractor& data)
34 Timer scoped_timer (__PRETTY_FUNCTION__,
35 "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
36 (uint64_t)data.GetByteSize());
37 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
39 log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize());
41 if (data.ValidOffset(0))
43 lldb::offset_t offset = 0;
45 DWARFDebugPubnamesSet set;
46 while (data.ValidOffset(offset))
48 if (set.Extract(data, &offset))
50 m_sets.push_back(set);
51 offset = set.GetOffsetOfNextEntry();
65 DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
67 Timer scoped_timer (__PRETTY_FUNCTION__,
68 "DWARFDebugPubnames::GeneratePubnames (data = %p)",
69 static_cast<void*>(dwarf2Data));
71 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
73 log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
74 static_cast<void*>(dwarf2Data));
77 DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
81 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
82 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
85 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
87 DWARFFormValue::FixedFormSizes fixed_form_sizes =
88 DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(),
91 bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
93 DWARFDIECollection dies;
94 const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
95 cu->AppendDIEsWithTag (DW_TAG_variable, dies);
97 dw_offset_t cu_offset = cu->GetOffset();
98 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
101 for (die_idx = 0; die_idx < die_count; ++die_idx)
103 DWARFDIE die = dies.GetDIEAtIndex(die_idx);
104 DWARFAttributes attributes;
105 const char *name = NULL;
106 const char *mangled = NULL;
107 bool add_die = false;
108 const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes);
109 if (num_attributes > 0)
113 dw_tag_t tag = die.Tag();
115 for (i=0; i<num_attributes; ++i)
117 dw_attr_t attr = attributes.AttributeAtIndex(i);
118 DWARFFormValue form_value;
122 if (attributes.ExtractFormValueAtIndex(i, form_value))
123 name = form_value.AsCString();
126 case DW_AT_MIPS_linkage_name:
127 case DW_AT_linkage_name:
128 if (attributes.ExtractFormValueAtIndex(i, form_value))
129 mangled = form_value.AsCString();
135 if (tag == DW_TAG_subprogram)
140 if (tag == DW_TAG_variable)
142 DWARFDIE parent_die = die.GetParent();
145 switch (parent_die.Tag())
147 case DW_TAG_subprogram:
148 case DW_TAG_lexical_block:
149 case DW_TAG_inlined_subroutine:
150 // Even if this is a function level static, we don't add it. We could theoretically
151 // add these if we wanted to by introspecting into the DW_AT_location and seeing
152 // if the location describes a hard coded address, but we don't want the performance
153 // penalty of that right now.
155 parent_die.Clear(); // Terminate the while loop.
158 case DW_TAG_compile_unit:
160 parent_die.Clear(); // Terminate the while loop.
164 parent_die = parent_die.GetParent(); // Keep going in the while loop.
174 if (add_die && (name || mangled))
176 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name);
180 if (pubnames_set.NumDescriptors() > 0)
182 m_sets.push_back(pubnames_set);
185 // Keep memory down by clearing DIEs if this generate function
186 // caused them to be parsed
188 cu->ClearDIEs (true);
199 DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
202 DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
206 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
207 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
209 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
210 DWARFDIECollection dies;
211 const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
212 dw_offset_t cu_offset = cu->GetOffset();
213 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
216 for (die_idx = 0; die_idx < die_count; ++die_idx)
218 DWARFDIE die = dies.GetDIEAtIndex (die_idx);
219 const char *name = die.GetName();
222 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
225 if (pubnames_set.NumDescriptors() > 0)
227 m_sets.push_back(pubnames_set);
231 return !m_sets.empty();
235 DWARFDebugPubnames::Dump(Log *s) const
238 s->PutCString("< EMPTY >\n");
242 const_iterator end = m_sets.end();
244 for (pos = m_sets.begin(); pos != end; ++pos)
250 DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
253 const_iterator end = m_sets.end();
257 for (pos = m_sets.begin(); pos != end; ++pos)
259 (*pos).Find(name, ignore_case, die_offsets);
262 return !die_offsets.empty();
266 DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
269 const_iterator end = m_sets.end();
273 for (pos = m_sets.begin(); pos != end; ++pos)
275 (*pos).Find(regex, die_offsets);
278 return !die_offsets.empty();