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/Utility/Stream.h"
13 #include "lldb/Utility/Timer.h"
15 #include "DWARFCompileUnit.h"
16 #include "DWARFDIECollection.h"
17 #include "DWARFDebugInfo.h"
18 #include "DWARFFormValue.h"
19 #include "LogChannelDWARF.h"
20 #include "SymbolFileDWARF.h"
23 using namespace lldb_private;
25 DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
27 bool DWARFDebugPubnames::Extract(const DWARFDataExtractor &data) {
28 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
29 Timer scoped_timer(func_cat,
30 "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
31 (uint64_t)data.GetByteSize());
32 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
34 log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
35 (uint64_t)data.GetByteSize());
37 if (data.ValidOffset(0)) {
38 lldb::offset_t offset = 0;
40 DWARFDebugPubnamesSet set;
41 while (data.ValidOffset(offset)) {
42 if (set.Extract(data, &offset)) {
43 m_sets.push_back(set);
44 offset = set.GetOffsetOfNextEntry();
55 bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
56 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
57 Timer scoped_timer(func_cat,
58 "DWARFDebugPubnames::GeneratePubnames (data = %p)",
59 static_cast<void *>(dwarf2Data));
61 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
63 log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
64 static_cast<void *>(dwarf2Data));
67 DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
70 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
71 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
73 DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
75 DWARFFormValue::FixedFormSizes fixed_form_sizes =
76 DWARFFormValue::GetFixedFormSizesForAddressSize(
77 cu->GetAddressByteSize(), cu->IsDWARF64());
79 bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
81 DWARFDIECollection dies;
82 const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
83 cu->AppendDIEsWithTag(DW_TAG_variable, dies);
85 dw_offset_t cu_offset = cu->GetOffset();
86 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
87 cu->GetNextCompileUnitOffset() -
91 for (die_idx = 0; die_idx < die_count; ++die_idx) {
92 DWARFDIE die = dies.GetDIEAtIndex(die_idx);
93 DWARFAttributes attributes;
94 const char *name = NULL;
95 const char *mangled = NULL;
97 const size_t num_attributes = die.GetDIE()->GetAttributes(
98 die.GetCU(), fixed_form_sizes, attributes);
99 if (num_attributes > 0) {
102 dw_tag_t tag = die.Tag();
104 for (i = 0; i < num_attributes; ++i) {
105 dw_attr_t attr = attributes.AttributeAtIndex(i);
106 DWARFFormValue form_value;
109 if (attributes.ExtractFormValueAtIndex(i, form_value))
110 name = form_value.AsCString();
113 case DW_AT_MIPS_linkage_name:
114 case DW_AT_linkage_name:
115 if (attributes.ExtractFormValueAtIndex(i, form_value))
116 mangled = form_value.AsCString();
122 if (tag == DW_TAG_subprogram)
127 if (tag == DW_TAG_variable) {
128 DWARFDIE parent_die = die.GetParent();
130 switch (parent_die.Tag()) {
131 case DW_TAG_subprogram:
132 case DW_TAG_lexical_block:
133 case DW_TAG_inlined_subroutine:
134 // Even if this is a function level static, we don't add it.
135 // We could theoretically
136 // add these if we wanted to by introspecting into the
137 // DW_AT_location and seeing
138 // if the location describes a hard coded address, but we
139 // don't want the performance
140 // penalty of that right now.
142 parent_die.Clear(); // Terminate the while loop.
145 case DW_TAG_compile_unit:
147 parent_die.Clear(); // Terminate the while loop.
152 parent_die.GetParent(); // Keep going in the while loop.
162 if (add_die && (name || mangled)) {
163 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
164 mangled ? mangled : name);
168 if (pubnames_set.NumDescriptors() > 0) {
169 m_sets.push_back(pubnames_set);
172 // Keep memory down by clearing DIEs if this generate function
173 // caused them to be parsed
185 bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
187 DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
190 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
191 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
192 DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
193 DWARFDIECollection dies;
194 const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_base_type, dies);
195 dw_offset_t cu_offset = cu->GetOffset();
196 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
197 cu->GetNextCompileUnitOffset() -
201 for (die_idx = 0; die_idx < die_count; ++die_idx) {
202 DWARFDIE die = dies.GetDIEAtIndex(die_idx);
203 const char *name = die.GetName();
206 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
209 if (pubnames_set.NumDescriptors() > 0) {
210 m_sets.push_back(pubnames_set);
214 return !m_sets.empty();
217 void DWARFDebugPubnames::Dump(Log *s) const {
219 s->PutCString("< EMPTY >\n");
222 const_iterator end = m_sets.end();
224 for (pos = m_sets.begin(); pos != end; ++pos)
229 bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
230 std::vector<dw_offset_t> &die_offsets) const {
232 const_iterator end = m_sets.end();
236 for (pos = m_sets.begin(); pos != end; ++pos) {
237 (*pos).Find(name, ignore_case, die_offsets);
240 return !die_offsets.empty();
243 bool DWARFDebugPubnames::Find(const RegularExpression ®ex,
244 std::vector<dw_offset_t> &die_offsets) const {
246 const_iterator end = m_sets.end();
250 for (pos = m_sets.begin(); pos != end; ++pos) {
251 (*pos).Find(regex, die_offsets);
254 return !die_offsets.empty();