]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
MFC r343601:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / SymbolFile / DWARF / DWARFDebugPubnames.cpp
1 //===-- DWARFDebugPubnames.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 "DWARFDebugPubnames.h"
11
12 #include "lldb/Utility/Stream.h"
13 #include "lldb/Utility/Timer.h"
14
15 #include "DWARFCompileUnit.h"
16 #include "DWARFDIECollection.h"
17 #include "DWARFDebugInfo.h"
18 #include "DWARFFormValue.h"
19 #include "LogChannelDWARF.h"
20 #include "SymbolFileDWARF.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25 DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
26
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));
33   if (log)
34     log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
35                 (uint64_t)data.GetByteSize());
36
37   if (data.ValidOffset(0)) {
38     lldb::offset_t offset = 0;
39
40     DWARFDebugPubnamesSet set;
41     while (data.ValidOffset(offset)) {
42       if (set.Extract(data, &offset)) {
43         m_sets.push_back(set);
44         offset = set.GetOffsetOfNextEntry();
45       } else
46         break;
47     }
48     if (log)
49       Dump(log);
50     return true;
51   }
52   return false;
53 }
54
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));
60
61   Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
62   if (log)
63     log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
64                 static_cast<void *>(dwarf2Data));
65
66   m_sets.clear();
67   DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
68   if (debug_info) {
69     uint32_t cu_idx = 0;
70     const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
71     for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
72
73       DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
74
75       DWARFFormValue::FixedFormSizes fixed_form_sizes =
76           DWARFFormValue::GetFixedFormSizesForAddressSize(
77               cu->GetAddressByteSize(), cu->IsDWARF64());
78
79       bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
80
81       DWARFDIECollection dies;
82       const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
83                                cu->AppendDIEsWithTag(DW_TAG_variable, dies);
84
85       dw_offset_t cu_offset = cu->GetOffset();
86       DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
87                                          cu->GetNextCompileUnitOffset() -
88                                              cu_offset);
89
90       size_t die_idx;
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;
96         bool add_die = false;
97         const size_t num_attributes = die.GetDIE()->GetAttributes(
98             die.GetCU(), fixed_form_sizes, attributes);
99         if (num_attributes > 0) {
100           uint32_t i;
101
102           dw_tag_t tag = die.Tag();
103
104           for (i = 0; i < num_attributes; ++i) {
105             dw_attr_t attr = attributes.AttributeAtIndex(i);
106             DWARFFormValue form_value;
107             switch (attr) {
108             case DW_AT_name:
109               if (attributes.ExtractFormValueAtIndex(i, form_value))
110                 name = form_value.AsCString();
111               break;
112
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();
117               break;
118
119             case DW_AT_low_pc:
120             case DW_AT_ranges:
121             case DW_AT_entry_pc:
122               if (tag == DW_TAG_subprogram)
123                 add_die = true;
124               break;
125
126             case DW_AT_location:
127               if (tag == DW_TAG_variable) {
128                 DWARFDIE parent_die = die.GetParent();
129                 while (parent_die) {
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.
141                     add_die = false;
142                     parent_die.Clear(); // Terminate the while loop.
143                     break;
144
145                   case DW_TAG_compile_unit:
146                     add_die = true;
147                     parent_die.Clear(); // Terminate the while loop.
148                     break;
149
150                   default:
151                     parent_die =
152                         parent_die.GetParent(); // Keep going in the while loop.
153                     break;
154                   }
155                 }
156               }
157               break;
158             }
159           }
160         }
161
162         if (add_die && (name || mangled)) {
163           pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
164                                      mangled ? mangled : name);
165         }
166       }
167
168       if (pubnames_set.NumDescriptors() > 0) {
169         m_sets.push_back(pubnames_set);
170       }
171
172       // Keep memory down by clearing DIEs if this generate function
173       // caused them to be parsed
174       if (clear_dies)
175         cu->ClearDIEs(true);
176     }
177   }
178   if (m_sets.empty())
179     return false;
180   if (log)
181     Dump(log);
182   return true;
183 }
184
185 bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
186   m_sets.clear();
187   DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
188   if (debug_info) {
189     uint32_t cu_idx = 0;
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() -
198                                              cu_offset);
199
200       size_t die_idx;
201       for (die_idx = 0; die_idx < die_count; ++die_idx) {
202         DWARFDIE die = dies.GetDIEAtIndex(die_idx);
203         const char *name = die.GetName();
204
205         if (name)
206           pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
207       }
208
209       if (pubnames_set.NumDescriptors() > 0) {
210         m_sets.push_back(pubnames_set);
211       }
212     }
213   }
214   return !m_sets.empty();
215 }
216
217 void DWARFDebugPubnames::Dump(Log *s) const {
218   if (m_sets.empty())
219     s->PutCString("< EMPTY >\n");
220   else {
221     const_iterator pos;
222     const_iterator end = m_sets.end();
223
224     for (pos = m_sets.begin(); pos != end; ++pos)
225       (*pos).Dump(s);
226   }
227 }
228
229 bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
230                               std::vector<dw_offset_t> &die_offsets) const {
231   const_iterator pos;
232   const_iterator end = m_sets.end();
233
234   die_offsets.clear();
235
236   for (pos = m_sets.begin(); pos != end; ++pos) {
237     (*pos).Find(name, ignore_case, die_offsets);
238   }
239
240   return !die_offsets.empty();
241 }
242
243 bool DWARFDebugPubnames::Find(const RegularExpression &regex,
244                               std::vector<dw_offset_t> &die_offsets) const {
245   const_iterator pos;
246   const_iterator end = m_sets.end();
247
248   die_offsets.clear();
249
250   for (pos = m_sets.begin(); pos != end; ++pos) {
251     (*pos).Find(regex, die_offsets);
252   }
253
254   return !die_offsets.empty();
255 }