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/Host/StringConvert.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/LineTable.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Utility/Timer.h"
19 
20 #include "DWARFDIECollection.h"
21 #include "DWARFDebugAbbrev.h"
22 #include "DWARFDebugAranges.h"
23 #include "DWARFDebugInfo.h"
24 #include "LogChannelDWARF.h"
25 #include "SymbolFileDWARFDebugMap.h"
26 #include "SymbolFileDWARFDwo.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace std;
31 
32 extern int g_verbose;
33 
34 DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) : m_dwarf(dwarf) {}
35 
36 DWARFUnit::~DWARFUnit() {}
37 
38 //----------------------------------------------------------------------
39 // ParseCompileUnitDIEsIfNeeded
40 //
41 // Parses a compile unit and indexes its DIEs if it hasn't already been done.
42 //----------------------------------------------------------------------
43 size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
44   size_t initial_die_array_size;
45   auto already_parsed = [cu_die_only, &initial_die_array_size, this]() -> bool {
46     initial_die_array_size = m_die_array.size();
47     return (cu_die_only && initial_die_array_size > 0)
48         || initial_die_array_size > 1;
49   };
50   {
51     llvm::sys::ScopedReader lock(m_extractdies_mutex);
52     if (already_parsed())
53       return 0;
54   }
55   llvm::sys::ScopedWriter lock(m_extractdies_mutex);
56   if (already_parsed())
57     return 0;
58 
59   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
60   Timer scoped_timer(
61       func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
62       m_offset, cu_die_only);
63 
64   // Set the offset to that of the first DIE and calculate the start of the
65   // next compilation unit header.
66   lldb::offset_t offset = GetFirstDIEOffset();
67   lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
68 
69   DWARFDebugInfoEntry die;
70   // Keep a flat array of the DIE for binary lookup by DIE offset
71   if (!cu_die_only) {
72     Log *log(
73         LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
74     if (log) {
75       m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
76           log,
77           "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at "
78           ".debug_info[0x%8.8x]",
79           GetOffset());
80     }
81   }
82 
83   uint32_t depth = 0;
84   // We are in our compile unit, parse starting at the offset we were told to
85   // parse
86   const DWARFDataExtractor &data = GetData();
87   std::vector<uint32_t> die_index_stack;
88   die_index_stack.reserve(32);
89   die_index_stack.push_back(0);
90   bool prev_die_had_children = false;
91   DWARFFormValue::FixedFormSizes fixed_form_sizes =
92       DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
93                                                       IsDWARF64());
94   while (offset < next_cu_offset &&
95          die.FastExtract(data, this, fixed_form_sizes, &offset)) {
96     //        if (log)
97     //            log->Printf("0x%8.8x: %*.*s%s%s",
98     //                        die.GetOffset(),
99     //                        depth * 2, depth * 2, "",
100     //                        DW_TAG_value_to_name (die.Tag()),
101     //                        die.HasChildren() ? " *" : "");
102 
103     const bool null_die = die.IsNULL();
104     if (depth == 0) {
105       if (initial_die_array_size == 0)
106         AddUnitDIE(die);
107       uint64_t base_addr = die.GetAttributeValueAsAddress(
108           m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
109       if (base_addr == LLDB_INVALID_ADDRESS)
110         base_addr =
111             die.GetAttributeValueAsAddress(m_dwarf, this, DW_AT_entry_pc, 0);
112       SetBaseAddress(base_addr);
113       if (cu_die_only)
114         return 1;
115     } else {
116       if (null_die) {
117         if (prev_die_had_children) {
118           // This will only happen if a DIE says is has children but all it
119           // contains is a NULL tag. Since we are removing the NULL DIEs from
120           // the list (saves up to 25% in C++ code), we need a way to let the
121           // DIE know that it actually doesn't have children.
122           if (!m_die_array.empty())
123             m_die_array.back().SetEmptyChildren(true);
124         }
125       } else {
126         die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
127 
128         if (die_index_stack.back())
129           m_die_array[die_index_stack.back()].SetSiblingIndex(
130               m_die_array.size() - die_index_stack.back());
131 
132         // Only push the DIE if it isn't a NULL DIE
133         m_die_array.push_back(die);
134       }
135     }
136 
137     if (null_die) {
138       // NULL DIE.
139       if (!die_index_stack.empty())
140         die_index_stack.pop_back();
141 
142       if (depth > 0)
143         --depth;
144       if (depth == 0)
145         break; // We are done with this compile unit!
146 
147       prev_die_had_children = false;
148     } else {
149       die_index_stack.back() = m_die_array.size() - 1;
150       // Normal DIE
151       const bool die_has_children = die.HasChildren();
152       if (die_has_children) {
153         die_index_stack.push_back(0);
154         ++depth;
155       }
156       prev_die_had_children = die_has_children;
157     }
158   }
159 
160   // Give a little bit of info if we encounter corrupt DWARF (our offset should
161   // always terminate at or before the start of the next compilation unit
162   // header).
163   if (offset > next_cu_offset) {
164     m_dwarf->GetObjectFile()->GetModule()->ReportWarning(
165         "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
166         "0x%8.8" PRIx64 "\n",
167         GetOffset(), offset);
168   }
169 
170   // Since std::vector objects will double their size, we really need to make a
171   // new array with the perfect size so we don't end up wasting space. So here
172   // we copy and swap to make sure we don't have any extra memory taken up.
173 
174   if (m_die_array.size() < m_die_array.capacity()) {
175     DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(),
176                                                          m_die_array.end());
177     exact_size_die_array.swap(m_die_array);
178   }
179   Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
180   if (log && log->GetVerbose()) {
181     StreamString strm;
182     Dump(&strm);
183     if (m_die_array.empty())
184       strm.Printf("error: no DIE for compile unit");
185     else
186       m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX);
187     log->PutString(strm.GetString());
188   }
189 
190   if (!m_dwo_symbol_file)
191     return m_die_array.size();
192 
193   DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
194   size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
195   return m_die_array.size() + dwo_die_count -
196          1; // We have 2 CU die, but we want to count it only as one
197 }
198 
199 void DWARFUnit::AddUnitDIE(DWARFDebugInfoEntry &die) {
200   assert(m_die_array.empty() && "Compile unit DIE already added");
201 
202   // The average bytes per DIE entry has been seen to be around 14-20 so lets
203   // pre-reserve half of that since we are now stripping the NULL tags.
204 
205   // Only reserve the memory if we are adding children of the main compile unit
206   // DIE. The compile unit DIE is always the first entry, so if our size is 1,
207   // then we are adding the first compile unit child DIE and should reserve the
208   // memory.
209   m_die_array.reserve(GetDebugInfoSize() / 24);
210   m_die_array.push_back(die);
211 
212   const DWARFDebugInfoEntry &cu_die = m_die_array.front();
213   std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
214       m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die);
215   if (!dwo_symbol_file)
216     return;
217 
218   DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
219   if (!dwo_cu)
220     return; // Can't fetch the compile unit from the dwo file.
221 
222   DWARFDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
223   if (!dwo_cu_die.IsValid())
224     return; // Can't fetch the compile unit DIE from the dwo file.
225 
226   uint64_t main_dwo_id =
227       cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0);
228   uint64_t sub_dwo_id =
229       dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
230   if (main_dwo_id != sub_dwo_id)
231     return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to
232   // a differectn compilation.
233 
234   m_dwo_symbol_file = std::move(dwo_symbol_file);
235 
236   dw_addr_t addr_base =
237       cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0);
238   dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
239       m_dwarf, this, DW_AT_GNU_ranges_base, 0);
240   dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
241 }
242 
243 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
244   if (DIE()) {
245     const DWARFDebugAranges &func_aranges = GetFunctionAranges();
246 
247     // Re-check the aranges auto pointer contents in case it was created above
248     if (!func_aranges.IsEmpty())
249       return GetDIE(func_aranges.FindAddress(address));
250   }
251   return DWARFDIE();
252 }
253 
254 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
255 				    DWARFDIECollection &dies,
256 				    uint32_t depth) const {
257   size_t old_size = dies.Size();
258   DWARFDebugInfoEntry::const_iterator pos;
259   DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
260   for (pos = m_die_array.begin(); pos != end; ++pos) {
261     if (pos->Tag() == tag)
262       dies.Append(DWARFDIE(this, &(*pos)));
263   }
264 
265   // Return the number of DIEs added to the collection
266   return dies.Size() - old_size;
267 }
268 
269 
270 lldb::user_id_t DWARFUnit::GetID() const {
271   dw_offset_t local_id =
272       m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
273   if (m_dwarf)
274     return DIERef(local_id, local_id).GetUID(m_dwarf);
275   else
276     return local_id;
277 }
278 
279 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const {
280   return m_offset + GetLengthByteSize() + GetLength();
281 }
282 
283 size_t DWARFUnit::GetDebugInfoSize() const {
284   return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
285 }
286 
287 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const {
288   return m_abbrevs;
289 }
290 
291 dw_offset_t DWARFUnit::GetAbbrevOffset() const {
292   return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
293 }
294 
295 void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
296                             dw_addr_t ranges_base,
297                             dw_offset_t base_obj_offset) {
298   m_addr_base = addr_base;
299   m_ranges_base = ranges_base;
300   m_base_obj_offset = base_obj_offset;
301 }
302 
303 void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) {
304   if (m_die_array.size() > 1) {
305     llvm::sys::ScopedWriter lock(m_extractdies_mutex);
306 
307     // std::vectors never get any smaller when resized to a smaller size, or
308     // when clear() or erase() are called, the size will report that it is
309     // smaller, but the memory allocated remains intact (call capacity() to see
310     // this). So we need to create a temporary vector and swap the contents
311     // which will cause just the internal pointers to be swapped so that when
312     // "tmp_array" goes out of scope, it will destroy the contents.
313 
314     // Save at least the compile unit DIE
315     DWARFDebugInfoEntry::collection tmp_array;
316     m_die_array.swap(tmp_array);
317     if (keep_compile_unit_die)
318       m_die_array.push_back(tmp_array.front());
319   }
320 
321   if (m_dwo_symbol_file)
322     m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
323 }
324 
325 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf,
326                                        DWARFDebugAranges *debug_aranges) {
327   // This function is usually called if there in no .debug_aranges section in
328   // order to produce a compile unit level set of address ranges that is
329   // accurate.
330 
331   size_t num_debug_aranges = debug_aranges->GetNumRanges();
332 
333   // First get the compile unit DIE only and check if it has a DW_AT_ranges
334   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
335 
336   const dw_offset_t cu_offset = GetOffset();
337   if (die) {
338     DWARFRangeList ranges;
339     const size_t num_ranges =
340         die->GetAttributeAddressRanges(dwarf, this, ranges, false);
341     if (num_ranges > 0) {
342       // This compile unit has DW_AT_ranges, assume this is correct if it is
343       // present since clang no longer makes .debug_aranges by default and it
344       // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with
345       // recent GCC builds.
346       for (size_t i = 0; i < num_ranges; ++i) {
347         const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
348         debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
349                                    range.GetRangeEnd());
350       }
351 
352       return; // We got all of our ranges from the DW_AT_ranges attribute
353     }
354   }
355   // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
356 
357   // If the DIEs weren't parsed, then we don't want all dies for all compile
358   // units to stay loaded when they weren't needed. So we can end up parsing
359   // the DWARF and then throwing them all away to keep memory usage down.
360   const bool clear_dies = ExtractDIEsIfNeeded(false) > 1;
361 
362   die = DIEPtr();
363   if (die)
364     die->BuildAddressRangeTable(dwarf, this, debug_aranges);
365 
366   if (debug_aranges->GetNumRanges() == num_debug_aranges) {
367     // We got nothing from the functions, maybe we have a line tables only
368     // situation. Check the line tables and build the arange table from this.
369     SymbolContext sc;
370     sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
371     if (sc.comp_unit) {
372       SymbolFileDWARFDebugMap *debug_map_sym_file =
373           m_dwarf->GetDebugMapSymfile();
374       if (debug_map_sym_file == NULL) {
375         LineTable *line_table = sc.comp_unit->GetLineTable();
376 
377         if (line_table) {
378           LineTable::FileAddressRanges file_ranges;
379           const bool append = true;
380           const size_t num_ranges =
381               line_table->GetContiguousFileAddressRanges(file_ranges, append);
382           for (uint32_t idx = 0; idx < num_ranges; ++idx) {
383             const LineTable::FileAddressRanges::Entry &range =
384                 file_ranges.GetEntryRef(idx);
385             debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
386                                        range.GetRangeEnd());
387           }
388         }
389       } else
390         debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges);
391     }
392   }
393 
394   if (debug_aranges->GetNumRanges() == num_debug_aranges) {
395     // We got nothing from the functions, maybe we have a line tables only
396     // situation. Check the line tables and build the arange table from this.
397     SymbolContext sc;
398     sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
399     if (sc.comp_unit) {
400       LineTable *line_table = sc.comp_unit->GetLineTable();
401 
402       if (line_table) {
403         LineTable::FileAddressRanges file_ranges;
404         const bool append = true;
405         const size_t num_ranges =
406             line_table->GetContiguousFileAddressRanges(file_ranges, append);
407         for (uint32_t idx = 0; idx < num_ranges; ++idx) {
408           const LineTable::FileAddressRanges::Entry &range =
409               file_ranges.GetEntryRef(idx);
410           debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
411                                      range.GetRangeEnd());
412         }
413       }
414     }
415   }
416 
417   // Keep memory down by clearing DIEs if this generate function caused them to
418   // be parsed
419   if (clear_dies)
420     ClearDIEs(true);
421 }
422 
423 lldb::ByteOrder DWARFUnit::GetByteOrder() const {
424   return m_dwarf->GetObjectFile()->GetByteOrder();
425 }
426 
427 TypeSystem *DWARFUnit::GetTypeSystem() {
428   if (m_dwarf)
429     return m_dwarf->GetTypeSystemForLanguage(GetLanguageType());
430   else
431     return nullptr;
432 }
433 
434 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() {
435   return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
436                                                          IsDWARF64());
437 }
438 
439 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
440 
441 bool DWARFUnit::HasDIEsParsed() const { return m_die_array.size() > 1; }
442 
443 //----------------------------------------------------------------------
444 // Compare function DWARFDebugAranges::Range structures
445 //----------------------------------------------------------------------
446 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
447                              const dw_offset_t die_offset) {
448   return die.GetOffset() < die_offset;
449 }
450 
451 //----------------------------------------------------------------------
452 // GetDIE()
453 //
454 // Get the DIE (Debug Information Entry) with the specified offset by first
455 // checking if the DIE is contained within this compile unit and grabbing the
456 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file.
457 //----------------------------------------------------------------------
458 DWARFDIE
459 DWARFUnit::GetDIE(dw_offset_t die_offset) {
460   if (die_offset != DW_INVALID_OFFSET) {
461     if (GetDwoSymbolFile())
462       return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
463 
464     if (ContainsDIEOffset(die_offset)) {
465       ExtractDIEsIfNeeded(false);
466       DWARFDebugInfoEntry::iterator end = m_die_array.end();
467       DWARFDebugInfoEntry::iterator pos =
468           lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
469       if (pos != end) {
470         if (die_offset == (*pos).GetOffset())
471           return DWARFDIE(this, &(*pos));
472       }
473     } else {
474       // Don't specify the compile unit offset as we don't know it because the
475       // DIE belongs to
476       // a different compile unit in the same symbol file.
477       return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset);
478     }
479   }
480   return DWARFDIE(); // Not found
481 }
482 
483 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
484   if (cu)
485     return cu->GetAddressByteSize();
486   return DWARFUnit::GetDefaultAddressSize();
487 }
488 
489 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) {
490   if (cu)
491     return cu->IsDWARF64();
492   return false;
493 }
494 
495 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; }
496 
497 void *DWARFUnit::GetUserData() const { return m_user_data; }
498 
499 void DWARFUnit::SetUserData(void *d) {
500   m_user_data = d;
501   if (m_dwo_symbol_file)
502     m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
503 }
504 
505 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
506   if (GetProducer() == eProducerLLVMGCC)
507     return false;
508   return true;
509 }
510 
511 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
512   // llvm-gcc makes completely invalid decl file attributes and won't ever be
513   // fixed, so we need to know to ignore these.
514   return GetProducer() == eProducerLLVMGCC;
515 }
516 
517 bool DWARFUnit::Supports_unnamed_objc_bitfields() {
518   if (GetProducer() == eProducerClang) {
519     const uint32_t major_version = GetProducerVersionMajor();
520     if (major_version > 425 ||
521         (major_version == 425 && GetProducerVersionUpdate() >= 13))
522       return true;
523     else
524       return false;
525   }
526   return true; // Assume all other compilers didn't have incorrect ObjC bitfield
527                // info
528 }
529 
530 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; }
531 
532 void DWARFUnit::ParseProducerInfo() {
533   m_producer_version_major = UINT32_MAX;
534   m_producer_version_minor = UINT32_MAX;
535   m_producer_version_update = UINT32_MAX;
536 
537   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
538   if (die) {
539 
540     const char *producer_cstr =
541         die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL);
542     if (producer_cstr) {
543       RegularExpression llvm_gcc_regex(
544           llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple "
545                           "Inc\\. build [0-9]+\\) \\(LLVM build "
546                           "[\\.0-9]+\\)$"));
547       if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) {
548         m_producer = eProducerLLVMGCC;
549       } else if (strstr(producer_cstr, "clang")) {
550         static RegularExpression g_clang_version_regex(
551             llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"));
552         RegularExpression::Match regex_match(3);
553         if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr),
554                                           &regex_match)) {
555           std::string str;
556           if (regex_match.GetMatchAtIndex(producer_cstr, 1, str))
557             m_producer_version_major =
558                 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
559           if (regex_match.GetMatchAtIndex(producer_cstr, 2, str))
560             m_producer_version_minor =
561                 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
562           if (regex_match.GetMatchAtIndex(producer_cstr, 3, str))
563             m_producer_version_update =
564                 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
565         }
566         m_producer = eProducerClang;
567       } else if (strstr(producer_cstr, "GNU"))
568         m_producer = eProducerGCC;
569     }
570   }
571   if (m_producer == eProducerInvalid)
572     m_producer = eProcucerOther;
573 }
574 
575 DWARFProducer DWARFUnit::GetProducer() {
576   if (m_producer == eProducerInvalid)
577     ParseProducerInfo();
578   return m_producer;
579 }
580 
581 uint32_t DWARFUnit::GetProducerVersionMajor() {
582   if (m_producer_version_major == 0)
583     ParseProducerInfo();
584   return m_producer_version_major;
585 }
586 
587 uint32_t DWARFUnit::GetProducerVersionMinor() {
588   if (m_producer_version_minor == 0)
589     ParseProducerInfo();
590   return m_producer_version_minor;
591 }
592 
593 uint32_t DWARFUnit::GetProducerVersionUpdate() {
594   if (m_producer_version_update == 0)
595     ParseProducerInfo();
596   return m_producer_version_update;
597 }
598 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) {
599   // Note: user languages between lo_user and hi_user must be handled
600   // explicitly here.
601   switch (val) {
602   case DW_LANG_Mips_Assembler:
603     return eLanguageTypeMipsAssembler;
604   case DW_LANG_GOOGLE_RenderScript:
605     return eLanguageTypeExtRenderScript;
606   default:
607     return static_cast<LanguageType>(val);
608   }
609 }
610 
611 LanguageType DWARFUnit::GetLanguageType() {
612   if (m_language_type != eLanguageTypeUnknown)
613     return m_language_type;
614 
615   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
616   if (die)
617     m_language_type = LanguageTypeFromDWARF(
618         die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0));
619   return m_language_type;
620 }
621 
622 bool DWARFUnit::GetIsOptimized() {
623   if (m_is_optimized == eLazyBoolCalculate) {
624     const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
625     if (die) {
626       m_is_optimized = eLazyBoolNo;
627       if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized,
628                                            0) == 1) {
629         m_is_optimized = eLazyBoolYes;
630       }
631     }
632   }
633   return m_is_optimized == eLazyBoolYes;
634 }
635 
636 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
637   return m_dwo_symbol_file.get();
638 }
639 
640 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; }
641 
642 void DWARFUnit::Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
643                       NameToDIE &func_methods, NameToDIE &func_selectors,
644                       NameToDIE &objc_class_selectors, NameToDIE &globals,
645                       NameToDIE &types, NameToDIE &namespaces) {
646   assert(!m_dwarf->GetBaseCompileUnit() &&
647          "DWARFUnit associated with .dwo or .dwp "
648          "should not be indexed directly");
649 
650   Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
651 
652   if (log) {
653     m_dwarf->GetObjectFile()->GetModule()->LogMessage(
654         log, "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]",
655         GetOffset());
656   }
657 
658   const LanguageType cu_language = GetLanguageType();
659   DWARFFormValue::FixedFormSizes fixed_form_sizes =
660       DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
661                                                       IsDWARF64());
662 
663   IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
664                func_fullnames, func_methods, func_selectors,
665                objc_class_selectors, globals, types, namespaces);
666 
667   SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
668   if (dwo_symbol_file) {
669     IndexPrivate(
670         dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes,
671         GetOffset(), func_basenames, func_fullnames, func_methods,
672         func_selectors, objc_class_selectors, globals, types, namespaces);
673   }
674 }
675 
676 void DWARFUnit::IndexPrivate(
677     DWARFUnit *dwarf_cu, const LanguageType cu_language,
678     const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
679     const dw_offset_t cu_offset, NameToDIE &func_basenames,
680     NameToDIE &func_fullnames, NameToDIE &func_methods,
681     NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
682     NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
683   DWARFDebugInfoEntry::const_iterator pos;
684   DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
685   DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
686   for (pos = begin; pos != end; ++pos) {
687     const DWARFDebugInfoEntry &die = *pos;
688 
689     const dw_tag_t tag = die.Tag();
690 
691     switch (tag) {
692     case DW_TAG_array_type:
693     case DW_TAG_base_type:
694     case DW_TAG_class_type:
695     case DW_TAG_constant:
696     case DW_TAG_enumeration_type:
697     case DW_TAG_inlined_subroutine:
698     case DW_TAG_namespace:
699     case DW_TAG_string_type:
700     case DW_TAG_structure_type:
701     case DW_TAG_subprogram:
702     case DW_TAG_subroutine_type:
703     case DW_TAG_typedef:
704     case DW_TAG_union_type:
705     case DW_TAG_unspecified_type:
706     case DW_TAG_variable:
707       break;
708 
709     default:
710       continue;
711     }
712 
713     DWARFAttributes attributes;
714     const char *name = NULL;
715     const char *mangled_cstr = NULL;
716     bool is_declaration = false;
717     // bool is_artificial = false;
718     bool has_address = false;
719     bool has_location_or_const_value = false;
720     bool is_global_or_static_variable = false;
721 
722     DWARFFormValue specification_die_form;
723     const size_t num_attributes =
724         die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
725     if (num_attributes > 0) {
726       for (uint32_t i = 0; i < num_attributes; ++i) {
727         dw_attr_t attr = attributes.AttributeAtIndex(i);
728         DWARFFormValue form_value;
729         switch (attr) {
730         case DW_AT_name:
731           if (attributes.ExtractFormValueAtIndex(i, form_value))
732             name = form_value.AsCString();
733           break;
734 
735         case DW_AT_declaration:
736           if (attributes.ExtractFormValueAtIndex(i, form_value))
737             is_declaration = form_value.Unsigned() != 0;
738           break;
739 
740         //                case DW_AT_artificial:
741         //                    if (attributes.ExtractFormValueAtIndex(i,
742         //                    form_value))
743         //                        is_artificial = form_value.Unsigned() != 0;
744         //                    break;
745 
746         case DW_AT_MIPS_linkage_name:
747         case DW_AT_linkage_name:
748           if (attributes.ExtractFormValueAtIndex(i, form_value))
749             mangled_cstr = form_value.AsCString();
750           break;
751 
752         case DW_AT_low_pc:
753         case DW_AT_high_pc:
754         case DW_AT_ranges:
755           has_address = true;
756           break;
757 
758         case DW_AT_entry_pc:
759           has_address = true;
760           break;
761 
762         case DW_AT_location:
763         case DW_AT_const_value:
764           has_location_or_const_value = true;
765           if (tag == DW_TAG_variable) {
766             const DWARFDebugInfoEntry *parent_die = die.GetParent();
767             while (parent_die != NULL) {
768               switch (parent_die->Tag()) {
769               case DW_TAG_subprogram:
770               case DW_TAG_lexical_block:
771               case DW_TAG_inlined_subroutine:
772                 // Even if this is a function level static, we don't add it. We
773                 // could theoretically add these if we wanted to by
774                 // introspecting into the DW_AT_location and seeing if the
775                 // location describes a hard coded address, but we don't want
776                 // the performance penalty of that right now.
777                 is_global_or_static_variable = false;
778                 // if (attributes.ExtractFormValueAtIndex(dwarf, i,
779                 //                                        form_value)) {
780                 //   // If we have valid block data, then we have location
781                 //   // expression bytesthat are fixed (not a location list).
782                 //   const uint8_t *block_data = form_value.BlockData();
783                 //   if (block_data) {
784                 //     uint32_t block_length = form_value.Unsigned();
785                 //     if (block_length == 1 +
786                 //     attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
787                 //       if (block_data[0] == DW_OP_addr)
788                 //         add_die = true;
789                 //     }
790                 //   }
791                 // }
792                 parent_die = NULL; // Terminate the while loop.
793                 break;
794 
795               case DW_TAG_compile_unit:
796               case DW_TAG_partial_unit:
797                 is_global_or_static_variable = true;
798                 parent_die = NULL; // Terminate the while loop.
799                 break;
800 
801               default:
802                 parent_die =
803                     parent_die->GetParent(); // Keep going in the while loop.
804                 break;
805               }
806             }
807           }
808           break;
809 
810         case DW_AT_specification:
811           if (attributes.ExtractFormValueAtIndex(i, form_value))
812             specification_die_form = form_value;
813           break;
814         }
815       }
816     }
817 
818     switch (tag) {
819     case DW_TAG_subprogram:
820       if (has_address) {
821         if (name) {
822           ObjCLanguage::MethodName objc_method(name, true);
823           if (objc_method.IsValid(true)) {
824             ConstString objc_class_name_with_category(
825                 objc_method.GetClassNameWithCategory());
826             ConstString objc_selector_name(objc_method.GetSelector());
827             ConstString objc_fullname_no_category_name(
828                 objc_method.GetFullNameWithoutCategory(true));
829             ConstString objc_class_name_no_category(objc_method.GetClassName());
830             func_fullnames.Insert(ConstString(name),
831                                   DIERef(cu_offset, die.GetOffset()));
832             if (objc_class_name_with_category)
833               objc_class_selectors.Insert(objc_class_name_with_category,
834                                           DIERef(cu_offset, die.GetOffset()));
835             if (objc_class_name_no_category &&
836                 objc_class_name_no_category != objc_class_name_with_category)
837               objc_class_selectors.Insert(objc_class_name_no_category,
838                                           DIERef(cu_offset, die.GetOffset()));
839             if (objc_selector_name)
840               func_selectors.Insert(objc_selector_name,
841                                     DIERef(cu_offset, die.GetOffset()));
842             if (objc_fullname_no_category_name)
843               func_fullnames.Insert(objc_fullname_no_category_name,
844                                     DIERef(cu_offset, die.GetOffset()));
845           }
846           // If we have a mangled name, then the DW_AT_name attribute is
847           // usually the method name without the class or any parameters
848           const DWARFDebugInfoEntry *parent = die.GetParent();
849           bool is_method = false;
850           if (parent) {
851             dw_tag_t parent_tag = parent->Tag();
852             if (parent_tag == DW_TAG_class_type ||
853                 parent_tag == DW_TAG_structure_type) {
854               is_method = true;
855             } else {
856               if (specification_die_form.IsValid()) {
857                 DWARFDIE specification_die =
858                     dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
859                         DIERef(specification_die_form));
860                 if (specification_die.GetParent().IsStructOrClass())
861                   is_method = true;
862               }
863             }
864           }
865 
866           if (is_method)
867             func_methods.Insert(ConstString(name),
868                                 DIERef(cu_offset, die.GetOffset()));
869           else
870             func_basenames.Insert(ConstString(name),
871                                   DIERef(cu_offset, die.GetOffset()));
872 
873           if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
874             func_fullnames.Insert(ConstString(name),
875                                   DIERef(cu_offset, die.GetOffset()));
876         }
877         if (mangled_cstr) {
878           // Make sure our mangled name isn't the same string table entry as
879           // our name. If it starts with '_', then it is ok, else compare the
880           // string to make sure it isn't the same and we don't end up with
881           // duplicate entries
882           if (name && name != mangled_cstr &&
883               ((mangled_cstr[0] == '_') ||
884                (::strcmp(name, mangled_cstr) != 0))) {
885             func_fullnames.Insert(ConstString(mangled_cstr),
886                                   DIERef(cu_offset, die.GetOffset()));
887           }
888         }
889       }
890       break;
891 
892     case DW_TAG_inlined_subroutine:
893       if (has_address) {
894         if (name)
895           func_basenames.Insert(ConstString(name),
896                                 DIERef(cu_offset, die.GetOffset()));
897         if (mangled_cstr) {
898           // Make sure our mangled name isn't the same string table entry as
899           // our name. If it starts with '_', then it is ok, else compare the
900           // string to make sure it isn't the same and we don't end up with
901           // duplicate entries
902           if (name && name != mangled_cstr &&
903               ((mangled_cstr[0] == '_') ||
904                (::strcmp(name, mangled_cstr) != 0))) {
905             func_fullnames.Insert(ConstString(mangled_cstr),
906                                   DIERef(cu_offset, die.GetOffset()));
907           }
908         } else
909           func_fullnames.Insert(ConstString(name),
910                                 DIERef(cu_offset, die.GetOffset()));
911       }
912       break;
913 
914     case DW_TAG_array_type:
915     case DW_TAG_base_type:
916     case DW_TAG_class_type:
917     case DW_TAG_constant:
918     case DW_TAG_enumeration_type:
919     case DW_TAG_string_type:
920     case DW_TAG_structure_type:
921     case DW_TAG_subroutine_type:
922     case DW_TAG_typedef:
923     case DW_TAG_union_type:
924     case DW_TAG_unspecified_type:
925       if (name && !is_declaration)
926         types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
927       if (mangled_cstr && !is_declaration)
928         types.Insert(ConstString(mangled_cstr),
929                      DIERef(cu_offset, die.GetOffset()));
930       break;
931 
932     case DW_TAG_namespace:
933       if (name)
934         namespaces.Insert(ConstString(name),
935                           DIERef(cu_offset, die.GetOffset()));
936       break;
937 
938     case DW_TAG_variable:
939       if (name && has_location_or_const_value && is_global_or_static_variable) {
940         globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
941         // Be sure to include variables by their mangled and demangled names if
942         // they have any since a variable can have a basename "i", a mangled
943         // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
944         // "(anonymous namespace)::i"...
945 
946         // Make sure our mangled name isn't the same string table entry as our
947         // name. If it starts with '_', then it is ok, else compare the string
948         // to make sure it isn't the same and we don't end up with duplicate
949         // entries
950         if (mangled_cstr && name != mangled_cstr &&
951             ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
952           Mangled mangled(ConstString(mangled_cstr), true);
953           globals.Insert(mangled.GetMangledName(),
954                          DIERef(cu_offset, die.GetOffset()));
955           ConstString demangled = mangled.GetDemangledName(cu_language);
956           if (demangled)
957             globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
958         }
959       }
960       break;
961 
962     default:
963       continue;
964     }
965   }
966 }
967 
968 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
969   if (m_func_aranges_ap.get() == NULL) {
970     m_func_aranges_ap.reset(new DWARFDebugAranges());
971     Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
972 
973     if (log) {
974       m_dwarf->GetObjectFile()->GetModule()->LogMessage(
975           log,
976           "DWARFUnit::GetFunctionAranges() for compile unit at "
977           ".debug_info[0x%8.8x]",
978           GetOffset());
979     }
980     const DWARFDebugInfoEntry *die = DIEPtr();
981     if (die)
982       die->BuildFunctionAddressRangeTable(m_dwarf, this,
983                                           m_func_aranges_ap.get());
984 
985     if (m_dwo_symbol_file) {
986       DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
987       const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr();
988       if (dwo_die)
989         dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu,
990                                                 m_func_aranges_ap.get());
991     }
992 
993     const bool minimize = false;
994     m_func_aranges_ap->Sort(minimize);
995   }
996   return *m_func_aranges_ap.get();
997 }
998 
999