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 "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 Timer scoped_timer(LLVM_PRETTY_FUNCTION,
29 "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
30 (uint64_t)data.GetByteSize());
31 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
33 log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
34 (uint64_t)data.GetByteSize());
36 if (data.ValidOffset(0)) {
37 lldb::offset_t offset = 0;
39 DWARFDebugPubnamesSet set;
40 while (data.ValidOffset(offset)) {
41 if (set.Extract(data, &offset)) {
42 m_sets.push_back(set);
43 offset = set.GetOffsetOfNextEntry();
54 bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
55 Timer scoped_timer(LLVM_PRETTY_FUNCTION,
56 "DWARFDebugPubnames::GeneratePubnames (data = %p)",
57 static_cast<void *>(dwarf2Data));
59 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
61 log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
62 static_cast<void *>(dwarf2Data));
65 DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
68 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
69 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
71 DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
73 DWARFFormValue::FixedFormSizes fixed_form_sizes =
74 DWARFFormValue::GetFixedFormSizesForAddressSize(
75 cu->GetAddressByteSize(), cu->IsDWARF64());
77 bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
79 DWARFDIECollection dies;
80 const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
81 cu->AppendDIEsWithTag(DW_TAG_variable, dies);
83 dw_offset_t cu_offset = cu->GetOffset();
84 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
85 cu->GetNextCompileUnitOffset() -
89 for (die_idx = 0; die_idx < die_count; ++die_idx) {
90 DWARFDIE die = dies.GetDIEAtIndex(die_idx);
91 DWARFAttributes attributes;
92 const char *name = NULL;
93 const char *mangled = NULL;
95 const size_t num_attributes = die.GetDIE()->GetAttributes(
96 die.GetCU(), fixed_form_sizes, attributes);
97 if (num_attributes > 0) {
100 dw_tag_t tag = die.Tag();
102 for (i = 0; i < num_attributes; ++i) {
103 dw_attr_t attr = attributes.AttributeAtIndex(i);
104 DWARFFormValue form_value;
107 if (attributes.ExtractFormValueAtIndex(i, form_value))
108 name = form_value.AsCString();
111 case DW_AT_MIPS_linkage_name:
112 case DW_AT_linkage_name:
113 if (attributes.ExtractFormValueAtIndex(i, form_value))
114 mangled = form_value.AsCString();
120 if (tag == DW_TAG_subprogram)
125 if (tag == DW_TAG_variable) {
126 DWARFDIE parent_die = die.GetParent();
128 switch (parent_die.Tag()) {
129 case DW_TAG_subprogram:
130 case DW_TAG_lexical_block:
131 case DW_TAG_inlined_subroutine:
132 // Even if this is a function level static, we don't add it.
133 // We could theoretically
134 // add these if we wanted to by introspecting into the
135 // DW_AT_location and seeing
136 // if the location describes a hard coded address, but we
137 // don't want the performance
138 // penalty of that right now.
140 parent_die.Clear(); // Terminate the while loop.
143 case DW_TAG_compile_unit:
145 parent_die.Clear(); // Terminate the while loop.
150 parent_die.GetParent(); // Keep going in the while loop.
160 if (add_die && (name || mangled)) {
161 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
162 mangled ? mangled : name);
166 if (pubnames_set.NumDescriptors() > 0) {
167 m_sets.push_back(pubnames_set);
170 // Keep memory down by clearing DIEs if this generate function
171 // caused them to be parsed
183 bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
185 DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
188 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
189 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
190 DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
191 DWARFDIECollection dies;
192 const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_base_type, dies);
193 dw_offset_t cu_offset = cu->GetOffset();
194 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
195 cu->GetNextCompileUnitOffset() -
199 for (die_idx = 0; die_idx < die_count; ++die_idx) {
200 DWARFDIE die = dies.GetDIEAtIndex(die_idx);
201 const char *name = die.GetName();
204 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
207 if (pubnames_set.NumDescriptors() > 0) {
208 m_sets.push_back(pubnames_set);
212 return !m_sets.empty();
215 void DWARFDebugPubnames::Dump(Log *s) const {
217 s->PutCString("< EMPTY >\n");
220 const_iterator end = m_sets.end();
222 for (pos = m_sets.begin(); pos != end; ++pos)
227 bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
228 std::vector<dw_offset_t> &die_offsets) const {
230 const_iterator end = m_sets.end();
234 for (pos = m_sets.begin(); pos != end; ++pos) {
235 (*pos).Find(name, ignore_case, die_offsets);
238 return !die_offsets.empty();
241 bool DWARFDebugPubnames::Find(const RegularExpression ®ex,
242 std::vector<dw_offset_t> &die_offsets) const {
244 const_iterator end = m_sets.end();
248 for (pos = m_sets.begin(); pos != end; ++pos) {
249 (*pos).Find(regex, die_offsets);
252 return !die_offsets.empty();