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