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