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