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