]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
MFV r296989:
[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 "DWARFDebugInfo.h"
16 #include "DWARFDIECollection.h"
17 #include "DWARFFormValue.h"
18 #include "DWARFCompileUnit.h"
19 #include "LogChannelDWARF.h"
20 #include "SymbolFileDWARF.h"
21
22
23 using namespace lldb;
24 using namespace lldb_private;
25
26 DWARFDebugPubnames::DWARFDebugPubnames() :
27     m_sets()
28 {
29 }
30
31 bool
32 DWARFDebugPubnames::Extract(const DWARFDataExtractor& data)
33 {
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));
38     if (log)
39         log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize());
40
41     if (data.ValidOffset(0))
42     {
43         lldb::offset_t offset = 0;
44
45         DWARFDebugPubnamesSet set;
46         while (data.ValidOffset(offset))
47         {
48             if (set.Extract(data, &offset))
49             {
50                 m_sets.push_back(set);
51                 offset = set.GetOffsetOfNextEntry();
52             }
53             else
54                 break;
55         }
56         if (log)
57             Dump (log);
58         return true;
59     }
60     return false;
61 }
62
63
64 bool
65 DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
66 {
67     Timer scoped_timer (__PRETTY_FUNCTION__,
68                         "DWARFDebugPubnames::GeneratePubnames (data = %p)",
69                         static_cast<void*>(dwarf2Data));
70
71     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
72     if (log)
73         log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
74                     static_cast<void*>(dwarf2Data));
75
76     m_sets.clear();
77     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
78     if (debug_info)
79     {
80         uint32_t cu_idx = 0;
81         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
82         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
83         {
84
85             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
86
87             DWARFFormValue::FixedFormSizes fixed_form_sizes =
88                 DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(),
89                                                                  cu->IsDWARF64());
90
91             bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
92
93             DWARFDIECollection dies;
94             const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
95                                      cu->AppendDIEsWithTag (DW_TAG_variable, dies);
96
97             dw_offset_t cu_offset = cu->GetOffset();
98             DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
99
100             size_t die_idx;
101             for (die_idx = 0; die_idx < die_count; ++die_idx)
102             {
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)
110                 {
111                     uint32_t i;
112
113                     dw_tag_t tag = die.Tag();
114                     
115                     for (i=0; i<num_attributes; ++i)
116                     {
117                         dw_attr_t attr = attributes.AttributeAtIndex(i);
118                         DWARFFormValue form_value;
119                         switch (attr)
120                         {
121                         case DW_AT_name:
122                             if (attributes.ExtractFormValueAtIndex(i, form_value))
123                                 name = form_value.AsCString();
124                             break;
125
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();
130                             break;
131
132                         case DW_AT_low_pc:
133                         case DW_AT_ranges:
134                         case DW_AT_entry_pc:
135                             if (tag == DW_TAG_subprogram)
136                                 add_die = true;
137                             break;
138
139                         case DW_AT_location:
140                             if (tag == DW_TAG_variable)
141                             {
142                                 DWARFDIE parent_die = die.GetParent();
143                                 while ( parent_die )
144                                 {
145                                     switch (parent_die.Tag())
146                                     {
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.
154                                         add_die = false;
155                                         parent_die.Clear();  // Terminate the while loop.
156                                         break;
157
158                                     case DW_TAG_compile_unit:
159                                         add_die = true;
160                                         parent_die.Clear();  // Terminate the while loop.
161                                         break;
162
163                                     default:
164                                         parent_die = parent_die.GetParent();   // Keep going in the while loop.
165                                         break;
166                                     }
167                                 }
168                             }
169                             break;
170                         }
171                     }
172                 }
173
174                 if (add_die && (name || mangled))
175                 {
176                     pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name);
177                 }
178             }
179
180             if (pubnames_set.NumDescriptors() > 0)
181             {
182                 m_sets.push_back(pubnames_set);
183             }
184             
185             // Keep memory down by clearing DIEs if this generate function
186             // caused them to be parsed
187             if (clear_dies)
188                 cu->ClearDIEs (true);
189         }
190     }
191     if (m_sets.empty())
192         return false;
193     if (log)
194         Dump (log);
195     return true;
196 }
197
198 bool
199 DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
200 {
201     m_sets.clear();
202     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
203     if (debug_info)
204     {
205         uint32_t cu_idx = 0;
206         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
207         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
208         {
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);
214
215             size_t die_idx;
216             for (die_idx = 0; die_idx < die_count; ++die_idx)
217             {
218                 DWARFDIE die = dies.GetDIEAtIndex (die_idx);
219                 const char *name = die.GetName();
220
221                 if (name)
222                     pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
223             }
224
225             if (pubnames_set.NumDescriptors() > 0)
226             {
227                 m_sets.push_back(pubnames_set);
228             }
229         }
230     }
231     return !m_sets.empty();
232 }
233
234 void
235 DWARFDebugPubnames::Dump(Log *s) const
236 {
237     if (m_sets.empty())
238         s->PutCString("< EMPTY >\n");
239     else
240     {
241         const_iterator pos;
242         const_iterator end = m_sets.end();
243
244         for (pos = m_sets.begin(); pos != end; ++pos)
245             (*pos).Dump(s);
246     }
247 }
248
249 bool
250 DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
251 {
252     const_iterator pos;
253     const_iterator end = m_sets.end();
254
255     die_offsets.clear();
256
257     for (pos = m_sets.begin(); pos != end; ++pos)
258     {
259         (*pos).Find(name, ignore_case, die_offsets);
260     }
261
262     return !die_offsets.empty();
263 }
264
265 bool
266 DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
267 {
268     const_iterator pos;
269     const_iterator end = m_sets.end();
270
271     die_offsets.clear();
272
273     for (pos = m_sets.begin(); pos != end; ++pos)
274     {
275         (*pos).Find(regex, die_offsets);
276     }
277
278     return !die_offsets.empty();
279 }