]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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                         dwarf2Data);
70
71     Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
72     if (log)
73         log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
74
75     m_sets.clear();
76     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
77     if (debug_info)
78     {
79
80         const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
81
82         uint32_t cu_idx = 0;
83         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
84         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
85         {
86
87             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
88
89             const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize());
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                 const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
104                 DWARFDebugInfoEntry::Attributes attributes;
105                 const char *name = NULL;
106                 const char *mangled = NULL;
107                 bool add_die = false;
108                 const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, 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(dwarf2Data, i, form_value))
123                                 name = form_value.AsCString(debug_str);
124                             break;
125
126                         case DW_AT_MIPS_linkage_name:
127                         case DW_AT_linkage_name:
128                             if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
129                                 mangled = form_value.AsCString(debug_str);
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                                 const DWARFDebugInfoEntry* parent_die = die->GetParent();
143                                 while ( parent_die != NULL )
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 //                                      if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
156 //                                      {
157 //                                          // If we have valid block data, then we have location expression bytes
158 //                                          // that are fixed (not a location list).
159 //                                          const uint8_t *block_data = form_value.BlockData();
160 //                                          if (block_data)
161 //                                          {
162 //                                              uint32_t block_length = form_value.Unsigned();
163 //                                              if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
164 //                                              {
165 //                                                  if (block_data[0] == DW_OP_addr)
166 //                                                      add_die = true;
167 //                                              }
168 //                                          }
169 //                                      }
170                                         parent_die = NULL;  // Terminate the while loop.
171                                         break;
172
173                                     case DW_TAG_compile_unit:
174                                         add_die = true;
175                                         parent_die = NULL;  // Terminate the while loop.
176                                         break;
177
178                                     default:
179                                         parent_die = parent_die->GetParent();   // Keep going in the while loop.
180                                         break;
181                                     }
182                                 }
183                             }
184                             break;
185                         }
186                     }
187                 }
188
189                 if (add_die && (name || mangled))
190                 {
191                     pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
192                 }
193             }
194
195             if (pubnames_set.NumDescriptors() > 0)
196             {
197                 m_sets.push_back(pubnames_set);
198             }
199             
200             // Keep memory down by clearing DIEs if this generate function
201             // caused them to be parsed
202             if (clear_dies)
203                 cu->ClearDIEs (true);
204         }
205     }
206     if (m_sets.empty())
207         return false;
208     if (log)
209         Dump (log);
210     return true;
211 }
212
213 bool
214 DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
215 {
216     m_sets.clear();
217     DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
218     if (debug_info)
219     {
220         uint32_t cu_idx = 0;
221         const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
222         for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
223         {
224             DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
225             DWARFDIECollection dies;
226             const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
227             dw_offset_t cu_offset = cu->GetOffset();
228             DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
229
230             size_t die_idx;
231             for (die_idx = 0; die_idx < die_count; ++die_idx)
232             {
233                 const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
234                 const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
235
236                 if (name)
237                 {
238                     pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
239                 }
240             }
241
242             if (pubnames_set.NumDescriptors() > 0)
243             {
244                 m_sets.push_back(pubnames_set);
245             }
246         }
247     }
248     return !m_sets.empty();
249 }
250
251 void
252 DWARFDebugPubnames::Dump(Log *s) const
253 {
254     if (m_sets.empty())
255         s->PutCString("< EMPTY >\n");
256     else
257     {
258         const_iterator pos;
259         const_iterator end = m_sets.end();
260
261         for (pos = m_sets.begin(); pos != end; ++pos)
262             (*pos).Dump(s);
263     }
264 }
265
266 bool
267 DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
268 {
269     const_iterator pos;
270     const_iterator end = m_sets.end();
271
272     die_offsets.clear();
273
274     for (pos = m_sets.begin(); pos != end; ++pos)
275     {
276         (*pos).Find(name, ignore_case, die_offsets);
277     }
278
279     return !die_offsets.empty();
280 }
281
282 bool
283 DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
284 {
285     const_iterator pos;
286     const_iterator end = m_sets.end();
287
288     die_offsets.clear();
289
290     for (pos = m_sets.begin(); pos != end; ++pos)
291     {
292         (*pos).Find(regex, die_offsets);
293     }
294
295     return !die_offsets.empty();
296 }