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