1 //===-- DWARFUnit.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 "DWARFUnit.h"
11 
12 #include "Plugins/Language/ObjC/ObjCLanguage.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Symbol/ObjectFile.h"
15 
16 #include "DWARFCompileUnit.h"
17 #include "DWARFDebugInfo.h"
18 #include "LogChannelDWARF.h"
19 #include "SymbolFileDWARFDwo.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace std;
24 
25 extern int g_verbose;
26 
27 DWARFUnit::DWARFUnit() {}
28 
29 DWARFUnit::~DWARFUnit() {}
30 
31 size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
32   return Data().ExtractDIEsIfNeeded(cu_die_only);
33 }
34 
35 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
36   return Data().LookupAddress(address);
37 }
38 
39 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
40 				    DWARFDIECollection &dies,
41 				    uint32_t depth) const {
42   return Data().AppendDIEsWithTag(tag, dies, depth);
43 }
44 
45 bool DWARFUnit::Verify(Stream *s) const {
46   return Data().Verify(s);
47 }
48 
49 void DWARFUnit::Dump(Stream *s) const {
50   Data().Dump(s);
51 }
52 
53 lldb::user_id_t DWARFUnit::GetID() const {
54   return Data().GetID();
55 }
56 
57 uint32_t DWARFUnit::Size() const { return IsDWARF64() ? 23 : 11; }
58 
59 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const {
60   return m_offset + (IsDWARF64() ? 12 : 4) + GetLength();
61 }
62 
63 size_t DWARFUnit::GetDebugInfoSize() const {
64   return (IsDWARF64() ? 12 : 4) + GetLength() - Size();
65 }
66 
67 uint32_t DWARFUnit::GetLength() const { return Data().m_length; }
68 uint16_t DWARFUnit::GetVersion() const { return Data().m_version; }
69 
70 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const {
71   return Data().m_abbrevs;
72 }
73 
74 dw_offset_t DWARFUnit::GetAbbrevOffset() const {
75   return Data().GetAbbrevOffset();
76 }
77 
78 uint8_t DWARFUnit::GetAddressByteSize() const { return Data().m_addr_size; }
79 
80 dw_addr_t DWARFUnit::GetBaseAddress() const { return Data().m_base_addr; }
81 
82 dw_addr_t DWARFUnit::GetAddrBase() const { return Data().m_addr_base; }
83 
84 dw_addr_t DWARFUnit::GetRangesBase() const { return Data().m_ranges_base; }
85 
86 void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
87                             dw_addr_t ranges_base,
88                             dw_offset_t base_obj_offset) {
89   Data().SetAddrBase(addr_base, ranges_base, base_obj_offset);
90 }
91 
92 void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) {
93   Data().ClearDIEs(keep_compile_unit_die);
94 }
95 
96 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
97                                        DWARFDebugAranges *debug_aranges) {
98   Data().BuildAddressRangeTable(dwarf2Data, debug_aranges);
99 }
100 
101 lldb::ByteOrder DWARFUnit::GetByteOrder() const {
102   return Data().m_dwarf2Data->GetObjectFile()->GetByteOrder();
103 }
104 
105 TypeSystem *DWARFUnit::GetTypeSystem() {
106   return Data().GetTypeSystem();
107 }
108 
109 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() {
110   return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
111                                                          IsDWARF64());
112 }
113 
114 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) {
115   Data().m_base_addr = base_addr;
116 }
117 
118 DWARFDIE DWARFUnit::GetCompileUnitDIEOnly() {
119   return Data().GetCompileUnitDIEOnly();
120 }
121 
122 DWARFDIE DWARFUnit::DIE() {
123   return Data().DIE();
124 }
125 
126 bool DWARFUnit::HasDIEsParsed() const { return Data().m_die_array.size() > 1; }
127 
128 //----------------------------------------------------------------------
129 // Compare function DWARFDebugAranges::Range structures
130 //----------------------------------------------------------------------
131 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
132                              const dw_offset_t die_offset) {
133   return die.GetOffset() < die_offset;
134 }
135 
136 //----------------------------------------------------------------------
137 // GetDIE()
138 //
139 // Get the DIE (Debug Information Entry) with the specified offset by
140 // first checking if the DIE is contained within this compile unit and
141 // grabbing the DIE from this compile unit. Otherwise we grab the DIE
142 // from the DWARF file.
143 //----------------------------------------------------------------------
144 DWARFDIE
145 DWARFUnit::GetDIE(dw_offset_t die_offset) {
146   if (die_offset != DW_INVALID_OFFSET) {
147     if (GetDwoSymbolFile())
148       return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
149 
150     if (ContainsDIEOffset(die_offset)) {
151       ExtractDIEsIfNeeded(false);
152       DWARFDebugInfoEntry::iterator end = Data().m_die_array.end();
153       DWARFDebugInfoEntry::iterator pos = lower_bound(
154           Data().m_die_array.begin(), end, die_offset, CompareDIEOffset);
155       if (pos != end) {
156         if (die_offset == (*pos).GetOffset())
157           return DWARFDIE(this, &(*pos));
158       }
159     } else {
160       // Don't specify the compile unit offset as we don't know it because the
161       // DIE belongs to
162       // a different compile unit in the same symbol file.
163       return Data().m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset);
164     }
165   }
166   return DWARFDIE(); // Not found
167 }
168 
169 static uint8_t g_default_addr_size = 4;
170 
171 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
172   if (cu)
173     return cu->GetAddressByteSize();
174   return DWARFCompileUnit::GetDefaultAddressSize();
175 }
176 
177 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) {
178   if (cu)
179     return cu->IsDWARF64();
180   return false;
181 }
182 
183 uint8_t DWARFUnit::GetDefaultAddressSize() {
184   return g_default_addr_size;
185 }
186 
187 void DWARFUnit::SetDefaultAddressSize(uint8_t addr_size) {
188   g_default_addr_size = addr_size;
189 }
190 
191 void *DWARFUnit::GetUserData() const { return Data().m_user_data; }
192 
193 void DWARFUnit::SetUserData(void *d) {
194   Data().SetUserData(d);
195 }
196 
197 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
198   if (GetProducer() == eProducerLLVMGCC)
199     return false;
200   return true;
201 }
202 
203 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
204   // llvm-gcc makes completely invalid decl file attributes and won't ever
205   // be fixed, so we need to know to ignore these.
206   return GetProducer() == eProducerLLVMGCC;
207 }
208 
209 bool DWARFUnit::Supports_unnamed_objc_bitfields() {
210   if (GetProducer() == eProducerClang) {
211     const uint32_t major_version = GetProducerVersionMajor();
212     if (major_version > 425 ||
213         (major_version == 425 && GetProducerVersionUpdate() >= 13))
214       return true;
215     else
216       return false;
217   }
218   return true; // Assume all other compilers didn't have incorrect ObjC bitfield
219                // info
220 }
221 
222 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const {
223   return Data().m_dwarf2Data;
224 }
225 
226 DWARFProducer DWARFUnit::GetProducer() {
227   return Data().GetProducer();
228 }
229 
230 uint32_t DWARFUnit::GetProducerVersionMajor() {
231   return Data().GetProducerVersionMajor();
232 }
233 
234 uint32_t DWARFUnit::GetProducerVersionMinor() {
235   return Data().GetProducerVersionMinor();
236 }
237 
238 uint32_t DWARFUnit::GetProducerVersionUpdate() {
239   return Data().GetProducerVersionUpdate();
240 }
241 
242 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) {
243   // Note: user languages between lo_user and hi_user
244   // must be handled explicitly here.
245   switch (val) {
246   case DW_LANG_Mips_Assembler:
247     return eLanguageTypeMipsAssembler;
248   case DW_LANG_GOOGLE_RenderScript:
249     return eLanguageTypeExtRenderScript;
250   default:
251     return static_cast<LanguageType>(val);
252   }
253 }
254 
255 LanguageType DWARFUnit::GetLanguageType() {
256   return Data().GetLanguageType();
257 }
258 
259 bool DWARFUnit::IsDWARF64() const { return Data().m_is_dwarf64; }
260 
261 bool DWARFUnit::GetIsOptimized() {
262   return Data().GetIsOptimized();
263 }
264 
265 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
266   return Data().m_dwo_symbol_file.get();
267 }
268 
269 dw_offset_t DWARFUnit::GetBaseObjOffset() const {
270   return Data().m_base_obj_offset;
271 }
272 
273 const DWARFDebugInfoEntry *DWARFUnit::GetCompileUnitDIEPtrOnly() {
274   return Data().GetCompileUnitDIEPtrOnly();
275 }
276 
277 const DWARFDebugInfoEntry *DWARFUnit::DIEPtr() {
278   return Data().DIEPtr();
279 }
280 
281 void DWARFUnit::Index(NameToDIE &func_basenames,
282                              NameToDIE &func_fullnames, NameToDIE &func_methods,
283                              NameToDIE &func_selectors,
284                              NameToDIE &objc_class_selectors,
285                              NameToDIE &globals, NameToDIE &types,
286                              NameToDIE &namespaces) {
287   assert(!Data().m_dwarf2Data->GetBaseCompileUnit() &&
288          "DWARFUnit associated with .dwo or .dwp "
289          "should not be indexed directly");
290 
291   Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
292 
293   if (log) {
294     Data().m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
295         log,
296         "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]",
297         GetOffset());
298   }
299 
300   const LanguageType cu_language = GetLanguageType();
301   DWARFFormValue::FixedFormSizes fixed_form_sizes =
302       DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
303                                                       IsDWARF64());
304 
305   IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
306                func_fullnames, func_methods, func_selectors,
307                objc_class_selectors, globals, types, namespaces);
308 
309   SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
310   if (dwo_symbol_file) {
311     IndexPrivate(
312         dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes,
313         GetOffset(), func_basenames, func_fullnames, func_methods,
314         func_selectors, objc_class_selectors, globals, types, namespaces);
315   }
316 }
317 
318 void DWARFUnit::IndexPrivate(
319     DWARFUnit *dwarf_cu, const LanguageType cu_language,
320     const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
321     const dw_offset_t cu_offset, NameToDIE &func_basenames,
322     NameToDIE &func_fullnames, NameToDIE &func_methods,
323     NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
324     NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
325   DWARFDebugInfoEntry::const_iterator pos;
326   DWARFDebugInfoEntry::const_iterator begin =
327       dwarf_cu->Data().m_die_array.begin();
328   DWARFDebugInfoEntry::const_iterator end = dwarf_cu->Data().m_die_array.end();
329   for (pos = begin; pos != end; ++pos) {
330     const DWARFDebugInfoEntry &die = *pos;
331 
332     const dw_tag_t tag = die.Tag();
333 
334     switch (tag) {
335     case DW_TAG_array_type:
336     case DW_TAG_base_type:
337     case DW_TAG_class_type:
338     case DW_TAG_constant:
339     case DW_TAG_enumeration_type:
340     case DW_TAG_inlined_subroutine:
341     case DW_TAG_namespace:
342     case DW_TAG_string_type:
343     case DW_TAG_structure_type:
344     case DW_TAG_subprogram:
345     case DW_TAG_subroutine_type:
346     case DW_TAG_typedef:
347     case DW_TAG_union_type:
348     case DW_TAG_unspecified_type:
349     case DW_TAG_variable:
350       break;
351 
352     default:
353       continue;
354     }
355 
356     DWARFAttributes attributes;
357     const char *name = NULL;
358     const char *mangled_cstr = NULL;
359     bool is_declaration = false;
360     // bool is_artificial = false;
361     bool has_address = false;
362     bool has_location_or_const_value = false;
363     bool is_global_or_static_variable = false;
364 
365     DWARFFormValue specification_die_form;
366     const size_t num_attributes =
367         die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
368     if (num_attributes > 0) {
369       for (uint32_t i = 0; i < num_attributes; ++i) {
370         dw_attr_t attr = attributes.AttributeAtIndex(i);
371         DWARFFormValue form_value;
372         switch (attr) {
373         case DW_AT_name:
374           if (attributes.ExtractFormValueAtIndex(i, form_value))
375             name = form_value.AsCString();
376           break;
377 
378         case DW_AT_declaration:
379           if (attributes.ExtractFormValueAtIndex(i, form_value))
380             is_declaration = form_value.Unsigned() != 0;
381           break;
382 
383         //                case DW_AT_artificial:
384         //                    if (attributes.ExtractFormValueAtIndex(i,
385         //                    form_value))
386         //                        is_artificial = form_value.Unsigned() != 0;
387         //                    break;
388 
389         case DW_AT_MIPS_linkage_name:
390         case DW_AT_linkage_name:
391           if (attributes.ExtractFormValueAtIndex(i, form_value))
392             mangled_cstr = form_value.AsCString();
393           break;
394 
395         case DW_AT_low_pc:
396         case DW_AT_high_pc:
397         case DW_AT_ranges:
398           has_address = true;
399           break;
400 
401         case DW_AT_entry_pc:
402           has_address = true;
403           break;
404 
405         case DW_AT_location:
406         case DW_AT_const_value:
407           has_location_or_const_value = true;
408           if (tag == DW_TAG_variable) {
409             const DWARFDebugInfoEntry *parent_die = die.GetParent();
410             while (parent_die != NULL) {
411               switch (parent_die->Tag()) {
412               case DW_TAG_subprogram:
413               case DW_TAG_lexical_block:
414               case DW_TAG_inlined_subroutine:
415                 // Even if this is a function level static, we don't add it. We
416                 // could theoretically
417                 // add these if we wanted to by introspecting into the
418                 // DW_AT_location and seeing
419                 // if the location describes a hard coded address, but we dont
420                 // want the performance
421                 // penalty of that right now.
422                 is_global_or_static_variable = false;
423                 //                              if
424                 //                              (attributes.ExtractFormValueAtIndex(dwarf2Data,
425                 //                              i, form_value))
426                 //                              {
427                 //                                  // If we have valid block
428                 //                                  data, then we have location
429                 //                                  expression bytes
430                 //                                  // that are fixed (not a
431                 //                                  location list).
432                 //                                  const uint8_t *block_data =
433                 //                                  form_value.BlockData();
434                 //                                  if (block_data)
435                 //                                  {
436                 //                                      uint32_t block_length =
437                 //                                      form_value.Unsigned();
438                 //                                      if (block_length == 1 +
439                 //                                      attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
440                 //                                      {
441                 //                                          if (block_data[0] ==
442                 //                                          DW_OP_addr)
443                 //                                              add_die = true;
444                 //                                      }
445                 //                                  }
446                 //                              }
447                 parent_die = NULL; // Terminate the while loop.
448                 break;
449 
450               case DW_TAG_compile_unit:
451                 is_global_or_static_variable = true;
452                 parent_die = NULL; // Terminate the while loop.
453                 break;
454 
455               default:
456                 parent_die =
457                     parent_die->GetParent(); // Keep going in the while loop.
458                 break;
459               }
460             }
461           }
462           break;
463 
464         case DW_AT_specification:
465           if (attributes.ExtractFormValueAtIndex(i, form_value))
466             specification_die_form = form_value;
467           break;
468         }
469       }
470     }
471 
472     switch (tag) {
473     case DW_TAG_subprogram:
474       if (has_address) {
475         if (name) {
476           ObjCLanguage::MethodName objc_method(name, true);
477           if (objc_method.IsValid(true)) {
478             ConstString objc_class_name_with_category(
479                 objc_method.GetClassNameWithCategory());
480             ConstString objc_selector_name(objc_method.GetSelector());
481             ConstString objc_fullname_no_category_name(
482                 objc_method.GetFullNameWithoutCategory(true));
483             ConstString objc_class_name_no_category(objc_method.GetClassName());
484             func_fullnames.Insert(ConstString(name),
485                                   DIERef(cu_offset, die.GetOffset()));
486             if (objc_class_name_with_category)
487               objc_class_selectors.Insert(objc_class_name_with_category,
488                                           DIERef(cu_offset, die.GetOffset()));
489             if (objc_class_name_no_category &&
490                 objc_class_name_no_category != objc_class_name_with_category)
491               objc_class_selectors.Insert(objc_class_name_no_category,
492                                           DIERef(cu_offset, die.GetOffset()));
493             if (objc_selector_name)
494               func_selectors.Insert(objc_selector_name,
495                                     DIERef(cu_offset, die.GetOffset()));
496             if (objc_fullname_no_category_name)
497               func_fullnames.Insert(objc_fullname_no_category_name,
498                                     DIERef(cu_offset, die.GetOffset()));
499           }
500           // If we have a mangled name, then the DW_AT_name attribute
501           // is usually the method name without the class or any parameters
502           const DWARFDebugInfoEntry *parent = die.GetParent();
503           bool is_method = false;
504           if (parent) {
505             dw_tag_t parent_tag = parent->Tag();
506             if (parent_tag == DW_TAG_class_type ||
507                 parent_tag == DW_TAG_structure_type) {
508               is_method = true;
509             } else {
510               if (specification_die_form.IsValid()) {
511                 DWARFDIE specification_die =
512                     dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
513                         DIERef(specification_die_form));
514                 if (specification_die.GetParent().IsStructOrClass())
515                   is_method = true;
516               }
517             }
518           }
519 
520           if (is_method)
521             func_methods.Insert(ConstString(name),
522                                 DIERef(cu_offset, die.GetOffset()));
523           else
524             func_basenames.Insert(ConstString(name),
525                                   DIERef(cu_offset, die.GetOffset()));
526 
527           if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
528             func_fullnames.Insert(ConstString(name),
529                                   DIERef(cu_offset, die.GetOffset()));
530         }
531         if (mangled_cstr) {
532           // Make sure our mangled name isn't the same string table entry
533           // as our name. If it starts with '_', then it is ok, else compare
534           // the string to make sure it isn't the same and we don't end up
535           // with duplicate entries
536           if (name && name != mangled_cstr &&
537               ((mangled_cstr[0] == '_') ||
538                (::strcmp(name, mangled_cstr) != 0))) {
539             Mangled mangled(ConstString(mangled_cstr), true);
540             func_fullnames.Insert(mangled.GetMangledName(),
541                                   DIERef(cu_offset, die.GetOffset()));
542             ConstString demangled = mangled.GetDemangledName(cu_language);
543             if (demangled)
544               func_fullnames.Insert(demangled,
545                                     DIERef(cu_offset, die.GetOffset()));
546           }
547         }
548       }
549       break;
550 
551     case DW_TAG_inlined_subroutine:
552       if (has_address) {
553         if (name)
554           func_basenames.Insert(ConstString(name),
555                                 DIERef(cu_offset, die.GetOffset()));
556         if (mangled_cstr) {
557           // Make sure our mangled name isn't the same string table entry
558           // as our name. If it starts with '_', then it is ok, else compare
559           // the string to make sure it isn't the same and we don't end up
560           // with duplicate entries
561           if (name && name != mangled_cstr &&
562               ((mangled_cstr[0] == '_') ||
563                (::strcmp(name, mangled_cstr) != 0))) {
564             Mangled mangled(ConstString(mangled_cstr), true);
565             func_fullnames.Insert(mangled.GetMangledName(),
566                                   DIERef(cu_offset, die.GetOffset()));
567             ConstString demangled = mangled.GetDemangledName(cu_language);
568             if (demangled)
569               func_fullnames.Insert(demangled,
570                                     DIERef(cu_offset, die.GetOffset()));
571           }
572         } else
573           func_fullnames.Insert(ConstString(name),
574                                 DIERef(cu_offset, die.GetOffset()));
575       }
576       break;
577 
578     case DW_TAG_array_type:
579     case DW_TAG_base_type:
580     case DW_TAG_class_type:
581     case DW_TAG_constant:
582     case DW_TAG_enumeration_type:
583     case DW_TAG_string_type:
584     case DW_TAG_structure_type:
585     case DW_TAG_subroutine_type:
586     case DW_TAG_typedef:
587     case DW_TAG_union_type:
588     case DW_TAG_unspecified_type:
589       if (name && !is_declaration)
590         types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
591       if (mangled_cstr && !is_declaration)
592         types.Insert(ConstString(mangled_cstr),
593                      DIERef(cu_offset, die.GetOffset()));
594       break;
595 
596     case DW_TAG_namespace:
597       if (name)
598         namespaces.Insert(ConstString(name),
599                           DIERef(cu_offset, die.GetOffset()));
600       break;
601 
602     case DW_TAG_variable:
603       if (name && has_location_or_const_value && is_global_or_static_variable) {
604         globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
605         // Be sure to include variables by their mangled and demangled
606         // names if they have any since a variable can have a basename
607         // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
608         // mangled name "(anonymous namespace)::i"...
609 
610         // Make sure our mangled name isn't the same string table entry
611         // as our name. If it starts with '_', then it is ok, else compare
612         // the string to make sure it isn't the same and we don't end up
613         // with duplicate entries
614         if (mangled_cstr && name != mangled_cstr &&
615             ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
616           Mangled mangled(ConstString(mangled_cstr), true);
617           globals.Insert(mangled.GetMangledName(),
618                          DIERef(cu_offset, die.GetOffset()));
619           ConstString demangled = mangled.GetDemangledName(cu_language);
620           if (demangled)
621             globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
622         }
623       }
624       break;
625 
626     default:
627       continue;
628     }
629   }
630 }
631