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