DWARFCompileUnit.cpp revision 258054
1893SN/A//===-- DWARFCompileUnit.cpp ------------------------------------*- C++ -*-===//
214643Salanb//
3893SN/A//                     The LLVM Compiler Infrastructure
4893SN/A//
5893SN/A// This file is distributed under the University of Illinois Open Source
6893SN/A// License. See LICENSE.TXT for details.
72362SN/A//
8893SN/A//===----------------------------------------------------------------------===//
92362SN/A
10893SN/A#include "DWARFCompileUnit.h"
11893SN/A
12893SN/A#include "lldb/Core/Mangled.h"
13893SN/A#include "lldb/Core/Module.h"
14893SN/A#include "lldb/Core/Stream.h"
15893SN/A#include "lldb/Core/Timer.h"
16893SN/A#include "lldb/Symbol/CompileUnit.h"
17893SN/A#include "lldb/Symbol/LineTable.h"
18893SN/A#include "lldb/Symbol/ObjectFile.h"
19893SN/A#include "lldb/Target/ObjCLanguageRuntime.h"
20893SN/A
212362SN/A#include "DWARFDebugAbbrev.h"
222362SN/A#include "DWARFDebugAranges.h"
232362SN/A#include "DWARFDebugInfo.h"
24893SN/A#include "DWARFDIECollection.h"
25893SN/A#include "DWARFFormValue.h"
26893SN/A#include "LogChannelDWARF.h"
27893SN/A#include "NameToDIE.h"
28893SN/A#include "SymbolFileDWARF.h"
29893SN/A#include "SymbolFileDWARFDebugMap.h"
30893SN/A
31893SN/Ausing namespace lldb;
32893SN/Ausing namespace lldb_private;
33893SN/Ausing namespace std;
34893SN/A
35893SN/A
36893SN/Aextern int g_verbose;
37893SN/A
38893SN/ADWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :
39893SN/A    m_dwarf2Data    (dwarf2Data),
40893SN/A    m_abbrevs       (NULL),
41893SN/A    m_user_data     (NULL),
4211179Sbpb    m_die_array     (),
43893SN/A    m_func_aranges_ap (),
44893SN/A    m_base_addr     (0),
45893SN/A    m_offset        (DW_INVALID_OFFSET),
46893SN/A    m_length        (0),
47893SN/A    m_version       (0),
48893SN/A    m_addr_size     (DWARFCompileUnit::GetDefaultAddressSize()),
49893SN/A    m_producer      (eProducerInvalid),
50893SN/A    m_producer_version_major (0),
51893SN/A    m_producer_version_minor (0),
52893SN/A    m_producer_version_update (0)
53893SN/A{
54893SN/A}
55893SN/A
56893SN/Avoid
57893SN/ADWARFCompileUnit::Clear()
58893SN/A{
59893SN/A    m_offset        = DW_INVALID_OFFSET;
60893SN/A    m_length        = 0;
61893SN/A    m_version       = 0;
62893SN/A    m_abbrevs       = NULL;
63893SN/A    m_addr_size     = DWARFCompileUnit::GetDefaultAddressSize();
64893SN/A    m_base_addr     = 0;
65893SN/A    m_die_array.clear();
66893SN/A    m_func_aranges_ap.reset();
67893SN/A    m_user_data     = NULL;
68893SN/A    m_producer      = eProducerInvalid;
69893SN/A}
70893SN/A
71893SN/Abool
72893SN/ADWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr)
73893SN/A{
74893SN/A    Clear();
75893SN/A
76893SN/A    m_offset = *offset_ptr;
77907SN/A
78907SN/A    if (debug_info.ValidOffset(*offset_ptr))
79907SN/A    {
80907SN/A        dw_offset_t abbr_offset;
81893SN/A        const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev();
82893SN/A        m_length        = debug_info.GetU32(offset_ptr);
83893SN/A        m_version       = debug_info.GetU16(offset_ptr);
84893SN/A        abbr_offset     = debug_info.GetU32(offset_ptr);
85893SN/A        m_addr_size     = debug_info.GetU8 (offset_ptr);
86893SN/A
87893SN/A        bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
88893SN/A        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
89907SN/A        bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
90893SN/A        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
91893SN/A
92893SN/A        if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL)
93893SN/A        {
94893SN/A            m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
95893SN/A            return true;
96893SN/A        }
97907SN/A
98893SN/A        // reset the offset to where we tried to parse from if anything went wrong
99907SN/A        *offset_ptr = m_offset;
100907SN/A    }
101907SN/A
102907SN/A    return false;
103893SN/A}
104893SN/A
105893SN/A
106907SN/Avoid
107907SN/ADWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
108907SN/A{
109907SN/A    if (m_die_array.size() > 1)
110907SN/A    {
111907SN/A        // std::vectors never get any smaller when resized to a smaller size,
112907SN/A        // or when clear() or erase() are called, the size will report that it
113907SN/A        // is smaller, but the memory allocated remains intact (call capacity()
114907SN/A        // to see this). So we need to create a temporary vector and swap the
115907SN/A        // contents which will cause just the internal pointers to be swapped
116907SN/A        // so that when "tmp_array" goes out of scope, it will destroy the
117907SN/A        // contents.
118893SN/A
119893SN/A        // Save at least the compile unit DIE
120893SN/A        DWARFDebugInfoEntry::collection tmp_array;
121893SN/A        m_die_array.swap(tmp_array);
122893SN/A        if (keep_compile_unit_die)
123907SN/A            m_die_array.push_back(tmp_array.front());
124907SN/A    }
125907SN/A}
126907SN/A
127907SN/A//----------------------------------------------------------------------
128907SN/A// ParseCompileUnitDIEsIfNeeded
129907SN/A//
130907SN/A// Parses a compile unit and indexes its DIEs if it hasn't already been
131907SN/A// done.
132907SN/A//----------------------------------------------------------------------
133907SN/Asize_t
1349720SN/ADWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
135907SN/A{
136907SN/A    const size_t initial_die_array_size = m_die_array.size();
137907SN/A    if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
138907SN/A        return 0; // Already parsed
139907SN/A
140907SN/A    Timer scoped_timer (__PRETTY_FUNCTION__,
141907SN/A                        "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
142907SN/A                        m_offset,
143907SN/A                        cu_die_only);
144907SN/A
145907SN/A    // Set the offset to that of the first DIE and calculate the start of the
146907SN/A    // next compilation unit header.
147907SN/A    lldb::offset_t offset = GetFirstDIEOffset();
148907SN/A    lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
149907SN/A
150907SN/A    DWARFDebugInfoEntry die;
151907SN/A        // Keep a flat array of the DIE for binary lookup by DIE offset
152907SN/A    if (!cu_die_only)
153907SN/A    {
154907SN/A        Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
155907SN/A        if (log)
156907SN/A        {
157907SN/A            m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
158907SN/A                                                                                    "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]",
159907SN/A                                                                                    GetOffset());
1601319SN/A        }
1611319SN/A    }
162907SN/A
163907SN/A    uint32_t depth = 0;
164893SN/A    // We are in our compile unit, parse starting at the offset
165893SN/A    // we were told to parse
166893SN/A    const DWARFDataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
167893SN/A    std::vector<uint32_t> die_index_stack;
168893SN/A    die_index_stack.reserve(32);
169893SN/A    die_index_stack.push_back(0);
170893SN/A    bool prev_die_had_children = false;
171893SN/A    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
172893SN/A    while (offset < next_cu_offset &&
173893SN/A           die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))
174893SN/A    {
175893SN/A//        if (log)
176893SN/A//            log->Printf("0x%8.8x: %*.*s%s%s",
177893SN/A//                        die.GetOffset(),
178893SN/A//                        depth * 2, depth * 2, "",
179893SN/A//                        DW_TAG_value_to_name (die.Tag()),
180893SN/A//                        die.HasChildren() ? " *" : "");
181893SN/A
182893SN/A        const bool null_die = die.IsNULL();
183893SN/A        if (depth == 0)
184893SN/A        {
185893SN/A            uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
186893SN/A            if (base_addr == LLDB_INVALID_ADDRESS)
187893SN/A                base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0);
188893SN/A            SetBaseAddress (base_addr);
189893SN/A            if (initial_die_array_size == 0)
190893SN/A                AddDIE (die);
191893SN/A            if (cu_die_only)
192893SN/A                return 1;
193893SN/A        }
194893SN/A        else
195893SN/A        {
196893SN/A            if (null_die)
197893SN/A            {
198893SN/A                if (prev_die_had_children)
199893SN/A                {
200893SN/A                    // This will only happen if a DIE says is has children
201893SN/A                    // but all it contains is a NULL tag. Since we are removing
202893SN/A                    // the NULL DIEs from the list (saves up to 25% in C++ code),
203893SN/A                    // we need a way to let the DIE know that it actually doesn't
204893SN/A                    // have children.
205893SN/A                    if (!m_die_array.empty())
206893SN/A                        m_die_array.back().SetEmptyChildren(true);
207893SN/A                }
208893SN/A            }
209893SN/A            else
210893SN/A            {
211893SN/A                die.SetParentIndex(m_die_array.size() - die_index_stack[depth-1]);
212893SN/A
213893SN/A                if (die_index_stack.back())
214893SN/A                    m_die_array[die_index_stack.back()].SetSiblingIndex(m_die_array.size()-die_index_stack.back());
215893SN/A
216893SN/A                // Only push the DIE if it isn't a NULL DIE
217893SN/A                    m_die_array.push_back(die);
218893SN/A            }
219893SN/A        }
220893SN/A
221893SN/A        if (null_die)
222893SN/A        {
223893SN/A            // NULL DIE.
2243471SN/A            if (!die_index_stack.empty())
2253471SN/A                die_index_stack.pop_back();
226893SN/A
227893SN/A            if (depth > 0)
228893SN/A                --depth;
229893SN/A            if (depth == 0)
230893SN/A                break;  // We are done with this compile unit!
231893SN/A
232893SN/A            prev_die_had_children = false;
233893SN/A        }
234893SN/A        else
235893SN/A        {
236893SN/A            die_index_stack.back() = m_die_array.size() - 1;
237893SN/A            // Normal DIE
238893SN/A            const bool die_has_children = die.HasChildren();
239893SN/A            if (die_has_children)
240893SN/A            {
241893SN/A                die_index_stack.push_back(0);
242893SN/A                ++depth;
243893SN/A            }
244893SN/A            prev_die_had_children = die_has_children;
245893SN/A        }
24614853Salanb    }
24714853Salanb
24814853Salanb    // Give a little bit of info if we encounter corrupt DWARF (our offset
24914853Salanb    // should always terminate at or before the start of the next compilation
250893SN/A    // unit header).
25114853Salanb    if (offset > next_cu_offset)
252893SN/A    {
253893SN/A        m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8" PRIx64 "\n",
254893SN/A                                                                   GetOffset(),
255893SN/A                                                                   offset);
256893SN/A    }
257893SN/A
258893SN/A    // Since std::vector objects will double their size, we really need to
259893SN/A    // make a new array with the perfect size so we don't end up wasting
260893SN/A    // space. So here we copy and swap to make sure we don't have any extra
261893SN/A    // memory taken up.
262893SN/A
263893SN/A    if (m_die_array.size () < m_die_array.capacity())
264893SN/A    {
265893SN/A        DWARFDebugInfoEntry::collection exact_size_die_array (m_die_array.begin(), m_die_array.end());
266893SN/A        exact_size_die_array.swap (m_die_array);
267893SN/A    }
268893SN/A    Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE));
269893SN/A    if (log)
270893SN/A    {
271893SN/A        StreamString strm;
272893SN/A        DWARFDebugInfoEntry::DumpDIECollection (strm, m_die_array);
273893SN/A        log->PutCString (strm.GetString().c_str());
274893SN/A    }
275893SN/A
276893SN/A    return m_die_array.size();
277893SN/A}
278893SN/A
279893SN/A
280893SN/Adw_offset_t
281893SN/ADWARFCompileUnit::GetAbbrevOffset() const
282893SN/A{
2833471SN/A    return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
2847115SN/A}
285893SN/A
286893SN/A
287893SN/A
288893SN/Abool
289893SN/ADWARFCompileUnit::Verify(Stream *s) const
290893SN/A{
291893SN/A    const DWARFDataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
292893SN/A    bool valid_offset = debug_info.ValidOffset(m_offset);
293893SN/A    bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
294893SN/A    bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
295893SN/A    bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
296893SN/A    bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
297893SN/A    bool verbose = s->GetVerbose();
298893SN/A    if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK)
299893SN/A    {
300893SN/A        if (verbose)
3013471SN/A            s->Printf("    0x%8.8x: OK\n", m_offset);
3023471SN/A        return true;
3033471SN/A    }
3043471SN/A    else
3053471SN/A    {
3063471SN/A        s->Printf("    0x%8.8x: ", m_offset);
3073471SN/A
3083471SN/A        m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
309893SN/A        s->EOL();
3103471SN/A        if (valid_offset)
3113471SN/A        {
3123471SN/A            if (!length_OK)
3133471SN/A                s->Printf("        The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length);
3143471SN/A            if (!version_OK)
315893SN/A                s->Printf("        The 16 bit compile unit header version is not supported.\n");
3163471SN/A            if (!abbr_offset_OK)
317893SN/A                s->Printf("        The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset());
318893SN/A            if (!addr_size_OK)
319893SN/A                s->Printf("        The address size is unsupported: 0x%2.2x\n", m_addr_size);
320893SN/A        }
321893SN/A        else
322893SN/A            s->Printf("        The start offset of the compile unit header in the .debug_info is invalid.\n");
323893SN/A    }
324893SN/A    return false;
325893SN/A}
326893SN/A
327893SN/A
328893SN/Avoid
329893SN/ADWARFCompileUnit::Dump(Stream *s) const
330893SN/A{
331893SN/A    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",
332893SN/A                m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset());
333893SN/A}
334893SN/A
335893SN/A
336893SN/Astatic uint8_t g_default_addr_size = 4;
337893SN/A
338893SN/Auint8_t
339893SN/ADWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu)
340893SN/A{
341893SN/A    if (cu)
342893SN/A        return cu->GetAddressByteSize();
343893SN/A    return DWARFCompileUnit::GetDefaultAddressSize();
344893SN/A}
345893SN/A
346893SN/Auint8_t
347893SN/ADWARFCompileUnit::GetDefaultAddressSize()
348893SN/A{
3493471SN/A    return g_default_addr_size;
3503471SN/A}
3513471SN/A
3523471SN/Avoid
3533471SN/ADWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
354893SN/A{
355893SN/A    g_default_addr_size = addr_size;
356893SN/A}
357893SN/A
358907SN/Avoid
359907SN/ADWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
360907SN/A                                          DWARFDebugAranges* debug_aranges,
361907SN/A                                          bool clear_dies_if_already_not_parsed)
362907SN/A{
363907SN/A    // This function is usually called if there in no .debug_aranges section
364893SN/A    // in order to produce a compile unit level set of address ranges that
365893SN/A    // is accurate. If the DIEs weren't parsed, then we don't want all dies for
366893SN/A    // all compile units to stay loaded when they weren't needed. So we can end
367893SN/A    // up parsing the DWARF and then throwing them all away to keep memory usage
368893SN/A    // down.
3693471SN/A    const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
370893SN/A
371893SN/A    const DWARFDebugInfoEntry* die = DIE();
372893SN/A    if (die)
373893SN/A        die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
374893SN/A
375893SN/A    if (debug_aranges->IsEmpty())
376893SN/A    {
377893SN/A        // We got nothing from the functions, maybe we have a line tables only
37815459Salanb        // situation. Check the line tables and build the arange table from this.
37915459Salanb        SymbolContext sc;
38015459Salanb        sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
38115459Salanb        if (sc.comp_unit)
38215459Salanb        {
38315459Salanb            SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf2Data->GetDebugMapSymfile();
38415459Salanb            if (debug_map_sym_file == NULL)
38515459Salanb            {
38615459Salanb                LineTable *line_table = sc.comp_unit->GetLineTable();
38715459Salanb
38815459Salanb                if (line_table)
38915459Salanb                {
39015459Salanb                    LineTable::FileAddressRanges file_ranges;
39115459Salanb                    const bool append = true;
392893SN/A                    const size_t num_ranges = line_table->GetContiguousFileAddressRanges (file_ranges, append);
393893SN/A                    for (uint32_t idx=0; idx<num_ranges; ++idx)
39415459Salanb                    {
39515459Salanb                        const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
3963471SN/A                        debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
397893SN/A                        printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
398893SN/A                    }
39915459Salanb                }
400893SN/A            }
401893SN/A            else
402893SN/A                debug_map_sym_file->AddOSOARanges(dwarf2Data,debug_aranges);
40315459Salanb        }
404893SN/A    }
405893SN/A
40611372Sbpb    // Keep memory down by clearing DIEs if this generate function
40711372Sbpb    // caused them to be parsed
40815459Salanb    if (clear_dies)
40915459Salanb        ClearDIEs (true);
41011372Sbpb
41115459Salanb}
41215459Salanb
41315459Salanb
41415459Salanbconst DWARFDebugAranges &
41515459SalanbDWARFCompileUnit::GetFunctionAranges ()
41615459Salanb{
41715459Salanb    if (m_func_aranges_ap.get() == NULL)
41815459Salanb    {
419893SN/A        m_func_aranges_ap.reset (new DWARFDebugAranges());
420893SN/A        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
42115459Salanb
422893SN/A        if (log)
423893SN/A        {
42415459Salanb            m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log,
425893SN/A                                                                    "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]",
426893SN/A                                                                    GetOffset());
427893SN/A        }
428893SN/A        const DWARFDebugInfoEntry* die = DIE();
42915459Salanb        if (die)
43015459Salanb            die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get());
43115459Salanb        const bool minimize = false;
43215459Salanb        m_func_aranges_ap->Sort(minimize);
43315459Salanb    }
43415459Salanb    return *m_func_aranges_ap.get();
43515459Salanb}
43615459Salanb
43715459Salanbbool
43815459SalanbDWARFCompileUnit::LookupAddress
43915459Salanb(
44015459Salanb    const dw_addr_t address,
44115459Salanb    DWARFDebugInfoEntry** function_die_handle,
44215459Salanb    DWARFDebugInfoEntry** block_die_handle
44315459Salanb)
44415459Salanb{
44515459Salanb    bool success = false;
44615459Salanb
44715459Salanb    if (function_die_handle != NULL && DIE())
44815459Salanb    {
44915459Salanb
45015459Salanb        const DWARFDebugAranges &func_aranges = GetFunctionAranges ();
45115459Salanb
45215459Salanb        // Re-check the aranges auto pointer contents in case it was created above
45315459Salanb        if (!func_aranges.IsEmpty())
45415459Salanb        {
45515459Salanb            *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address));
45615459Salanb            if (*function_die_handle != NULL)
45715459Salanb            {
45815459Salanb                success = true;
45915459Salanb                if (block_die_handle != NULL)
460893SN/A                {
46115459Salanb                    DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild();
462893SN/A                    while (child)
463893SN/A                    {
464893SN/A                        if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle))
465893SN/A                            break;
46615459Salanb                        child = child->GetSibling();
46715459Salanb                    }
46815459Salanb                }
46914853Salanb            }
47014853Salanb        }
471893SN/A    }
472893SN/A    return success;
47315459Salanb}
474893SN/A
475893SN/A//----------------------------------------------------------------------
476893SN/A// Compare function DWARFDebugAranges::Range structures
477893SN/A//----------------------------------------------------------------------
478893SN/Astatic bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
47915459Salanb{
480893SN/A    return die1.GetOffset() < die2.GetOffset();
4813471SN/A}
482893SN/A
483893SN/A//----------------------------------------------------------------------
484893SN/A// GetDIEPtr()
485893SN/A//
486893SN/A// Get the DIE (Debug Information Entry) with the specified offset.
4878565SN/A//----------------------------------------------------------------------
488893SN/ADWARFDebugInfoEntry*
489893SN/ADWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset)
490893SN/A{
491893SN/A    if (die_offset != DW_INVALID_OFFSET)
492893SN/A    {
493893SN/A        ExtractDIEsIfNeeded (false);
494893SN/A        DWARFDebugInfoEntry compare_die;
495893SN/A        compare_die.SetOffset(die_offset);
496893SN/A        DWARFDebugInfoEntry::iterator end = m_die_array.end();
497893SN/A        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
498893SN/A        if (pos != end)
499893SN/A        {
500893SN/A            if (die_offset == (*pos).GetOffset())
501893SN/A                return &(*pos);
502893SN/A        }
503893SN/A    }
504893SN/A    return NULL;    // Not found in any compile units
505893SN/A}
506893SN/A
507893SN/A//----------------------------------------------------------------------
508893SN/A// GetDIEPtrContainingOffset()
509893SN/A//
510893SN/A// Get the DIE (Debug Information Entry) that contains the specified
511893SN/A// .debug_info offset.
512893SN/A//----------------------------------------------------------------------
513893SN/Aconst DWARFDebugInfoEntry*
514893SN/ADWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset)
515893SN/A{
516893SN/A    if (die_offset != DW_INVALID_OFFSET)
517893SN/A    {
518893SN/A        ExtractDIEsIfNeeded (false);
519893SN/A        DWARFDebugInfoEntry compare_die;
520893SN/A        compare_die.SetOffset(die_offset);
521893SN/A        DWARFDebugInfoEntry::iterator end = m_die_array.end();
522893SN/A        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
523893SN/A        if (pos != end)
524893SN/A        {
525893SN/A            if (die_offset >= (*pos).GetOffset())
526893SN/A            {
527893SN/A                DWARFDebugInfoEntry::iterator next = pos + 1;
528893SN/A                if (next != end)
529893SN/A                {
530893SN/A                    if (die_offset < (*next).GetOffset())
531893SN/A                        return &(*pos);
532893SN/A                }
533893SN/A            }
534893SN/A        }
535893SN/A    }
536893SN/A    return NULL;    // Not found in any compile units
537893SN/A}
538893SN/A
539893SN/A
540893SN/A
541893SN/Asize_t
542893SN/ADWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
543893SN/A{
544893SN/A    size_t old_size = dies.Size();
545893SN/A    DWARFDebugInfoEntry::const_iterator pos;
546893SN/A    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
547893SN/A    for (pos = m_die_array.begin(); pos != end; ++pos)
548893SN/A    {
549893SN/A        if (pos->Tag() == tag)
550893SN/A            dies.Append (&(*pos));
551893SN/A    }
552893SN/A
553893SN/A    // Return the number of DIEs added to the collection
554893SN/A    return dies.Size() - old_size;
555893SN/A}
556893SN/A
557893SN/A//void
558893SN/A//DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx)
5593471SN/A//{
560893SN/A//    m_global_die_indexes.push_back (die_idx);
561893SN/A//}
562893SN/A//
563893SN/A//
564893SN/A//void
565893SN/A//DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die)
566893SN/A//{
567893SN/A//    // Indexes to all file level global and static variables
5683471SN/A//    m_global_die_indexes;
569893SN/A//
570893SN/A//    if (m_die_array.empty())
571893SN/A//        return;
572893SN/A//
573893SN/A//    const DWARFDebugInfoEntry* first_die = &m_die_array[0];
574893SN/A//    const DWARFDebugInfoEntry* end = first_die + m_die_array.size();
575893SN/A//    if (first_die <= die && die < end)
576893SN/A//        m_global_die_indexes.push_back (die - first_die);
577893SN/A//}
578893SN/A
579893SN/A
5803471SN/Avoid
5813471SN/ADWARFCompileUnit::Index (const uint32_t cu_idx,
582893SN/A                         NameToDIE& func_basenames,
583893SN/A                         NameToDIE& func_fullnames,
584893SN/A                         NameToDIE& func_methods,
585893SN/A                         NameToDIE& func_selectors,
586893SN/A                         NameToDIE& objc_class_selectors,
587893SN/A                         NameToDIE& globals,
588893SN/A                         NameToDIE& types,
589893SN/A                         NameToDIE& namespaces)
590893SN/A{
591893SN/A    const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
592893SN/A
593893SN/A    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
594893SN/A
595893SN/A    Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));
596893SN/A
597893SN/A    if (log)
598893SN/A    {
599893SN/A        m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log,
600893SN/A                                                                "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
601893SN/A                                                                GetOffset());
602893SN/A    }
603893SN/A
604893SN/A    DWARFDebugInfoEntry::const_iterator pos;
605893SN/A    DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
606893SN/A    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
607893SN/A    for (pos = begin; pos != end; ++pos)
608893SN/A    {
609893SN/A        const DWARFDebugInfoEntry &die = *pos;
610893SN/A
611893SN/A        const dw_tag_t tag = die.Tag();
612893SN/A
613893SN/A        switch (tag)
614893SN/A        {
615893SN/A        case DW_TAG_subprogram:
616893SN/A        case DW_TAG_inlined_subroutine:
617893SN/A        case DW_TAG_base_type:
618893SN/A        case DW_TAG_class_type:
619893SN/A        case DW_TAG_constant:
620893SN/A        case DW_TAG_enumeration_type:
621893SN/A        case DW_TAG_string_type:
622893SN/A        case DW_TAG_subroutine_type:
623893SN/A        case DW_TAG_structure_type:
624893SN/A        case DW_TAG_union_type:
625893SN/A        case DW_TAG_typedef:
626893SN/A        case DW_TAG_namespace:
627893SN/A        case DW_TAG_variable:
628893SN/A        case DW_TAG_unspecified_type:
629893SN/A            break;
630893SN/A
631893SN/A        default:
632893SN/A            continue;
6333471SN/A        }
6343471SN/A
6353471SN/A        DWARFDebugInfoEntry::Attributes attributes;
6363471SN/A        const char *name = NULL;
6373471SN/A        const char *mangled_cstr = NULL;
6383471SN/A        bool is_declaration = false;
6393471SN/A        //bool is_artificial = false;
6403471SN/A        bool has_address = false;
6413471SN/A        bool has_location = false;
6423471SN/A        bool is_global_or_static_variable = false;
6433471SN/A
6443471SN/A        dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
6453471SN/A        const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes);
6463471SN/A        if (num_attributes > 0)
6473471SN/A        {
6483471SN/A            for (uint32_t i=0; i<num_attributes; ++i)
649893SN/A            {
650893SN/A                dw_attr_t attr = attributes.AttributeAtIndex(i);
651893SN/A                DWARFFormValue form_value;
652893SN/A                switch (attr)
653893SN/A                {
654893SN/A                case DW_AT_name:
655893SN/A                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
656893SN/A                        name = form_value.AsCString(debug_str);
657893SN/A                    break;
658893SN/A
659893SN/A                case DW_AT_declaration:
660893SN/A                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
661893SN/A                        is_declaration = form_value.Unsigned() != 0;
662893SN/A                    break;
663893SN/A
664893SN/A//                case DW_AT_artificial:
665893SN/A//                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
666893SN/A//                        is_artificial = form_value.Unsigned() != 0;
667893SN/A//                    break;
668893SN/A
669893SN/A                case DW_AT_MIPS_linkage_name:
670893SN/A                case DW_AT_linkage_name:
671893SN/A                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
672893SN/A                        mangled_cstr = form_value.AsCString(debug_str);
673893SN/A                    break;
674893SN/A
675893SN/A                case DW_AT_low_pc:
676893SN/A                case DW_AT_high_pc:
677893SN/A                case DW_AT_ranges:
678893SN/A                    has_address = true;
679893SN/A                    break;
680893SN/A
681893SN/A                case DW_AT_entry_pc:
682893SN/A                    has_address = true;
683893SN/A                    break;
684893SN/A
685893SN/A                case DW_AT_location:
686893SN/A                    has_location = true;
687893SN/A                    if (tag == DW_TAG_variable)
688893SN/A                    {
689893SN/A                        const DWARFDebugInfoEntry* parent_die = die.GetParent();
690893SN/A                        while ( parent_die != NULL )
691893SN/A                        {
692893SN/A                            switch (parent_die->Tag())
693893SN/A                            {
694893SN/A                            case DW_TAG_subprogram:
695893SN/A                            case DW_TAG_lexical_block:
696893SN/A                            case DW_TAG_inlined_subroutine:
697893SN/A                                // Even if this is a function level static, we don't add it. We could theoretically
698893SN/A                                // add these if we wanted to by introspecting into the DW_AT_location and seeing
699893SN/A                                // if the location describes a hard coded address, but we dont want the performance
700893SN/A                                // penalty of that right now.
701893SN/A                                is_global_or_static_variable = false;
702893SN/A//                              if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
703893SN/A//                              {
7043779SN/A//                                  // If we have valid block data, then we have location expression bytes
7053779SN/A//                                  // that are fixed (not a location list).
7063779SN/A//                                  const uint8_t *block_data = form_value.BlockData();
707893SN/A//                                  if (block_data)
708893SN/A//                                  {
7093471SN/A//                                      uint32_t block_length = form_value.Unsigned();
710893SN/A//                                      if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
7113471SN/A//                                      {
7123471SN/A//                                          if (block_data[0] == DW_OP_addr)
7133471SN/A//                                              add_die = true;
7143471SN/A//                                      }
7153471SN/A//                                  }
716893SN/A//                              }
717893SN/A                                parent_die = NULL;  // Terminate the while loop.
718893SN/A                                break;
719893SN/A
720893SN/A                            case DW_TAG_compile_unit:
721893SN/A                                is_global_or_static_variable = true;
722893SN/A                                parent_die = NULL;  // Terminate the while loop.
723893SN/A                                break;
724893SN/A
725893SN/A                            default:
726893SN/A                                parent_die = parent_die->GetParent();   // Keep going in the while loop.
727893SN/A                                break;
728893SN/A                            }
729893SN/A                        }
730893SN/A                    }
731893SN/A                    break;
732893SN/A
733893SN/A                case DW_AT_specification:
734893SN/A                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
7353779SN/A                        specification_die_offset = form_value.Reference(this);
7363779SN/A                    break;
7373779SN/A                }
738893SN/A            }
739893SN/A        }
7403471SN/A
741893SN/A        switch (tag)
742893SN/A        {
743893SN/A        case DW_TAG_subprogram:
7443471SN/A            if (has_address)
7453471SN/A            {
7463471SN/A                if (name)
7473471SN/A                {
7483471SN/A                    // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the
749893SN/A                    // simple inlined check outside the call.
750893SN/A                    ObjCLanguageRuntime::MethodName objc_method(name, true);
751893SN/A                    if (objc_method.IsValid(true))
752893SN/A                    {
753893SN/A                        ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());
754893SN/A                        ConstString objc_selector_name (objc_method.GetSelector());
755893SN/A                        ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));
756893SN/A                        ConstString objc_class_name_no_category (objc_method.GetClassName());
757893SN/A                        func_fullnames.Insert (ConstString(name), die.GetOffset());
758893SN/A                        if (objc_class_name_with_category)
759893SN/A                            objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset());
760893SN/A                        if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category)
761893SN/A                            objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset());
762893SN/A                        if (objc_selector_name)
763893SN/A                            func_selectors.Insert (objc_selector_name, die.GetOffset());
764893SN/A                        if (objc_fullname_no_category_name)
765893SN/A                            func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
766893SN/A                    }
767893SN/A                    // If we have a mangled name, then the DW_AT_name attribute
768893SN/A                    // is usually the method name without the class or any parameters
769893SN/A                    const DWARFDebugInfoEntry *parent = die.GetParent();
770893SN/A                    bool is_method = false;
771893SN/A                    if (parent)
772893SN/A                    {
773893SN/A                        dw_tag_t parent_tag = parent->Tag();
774893SN/A                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
775893SN/A                        {
776893SN/A                            is_method = true;
777893SN/A                        }
778893SN/A                        else
779893SN/A                        {
780893SN/A                            if (specification_die_offset != DW_INVALID_OFFSET)
781893SN/A                            {
782893SN/A                                const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL);
783893SN/A                                if (specification_die)
784893SN/A                                {
785893SN/A                                    parent = specification_die->GetParent();
786893SN/A                                    if (parent)
787893SN/A                                    {
788893SN/A                                        parent_tag = parent->Tag();
789893SN/A
790893SN/A                                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
791893SN/A                                            is_method = true;
792893SN/A                                    }
793893SN/A                                }
794893SN/A                            }
795893SN/A                        }
796893SN/A                    }
797893SN/A
798893SN/A
799893SN/A                    if (is_method)
800893SN/A                        func_methods.Insert (ConstString(name), die.GetOffset());
801893SN/A                    else
802893SN/A                        func_basenames.Insert (ConstString(name), die.GetOffset());
803893SN/A
804893SN/A                    if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
805893SN/A                        func_fullnames.Insert (ConstString(name), die.GetOffset());
806893SN/A                }
807893SN/A                if (mangled_cstr)
808893SN/A                {
809893SN/A                    // Make sure our mangled name isn't the same string table entry
810893SN/A                    // as our name. If it starts with '_', then it is ok, else compare
811893SN/A                    // the string to make sure it isn't the same and we don't end up
812893SN/A                    // with duplicate entries
813893SN/A                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))
814893SN/A                    {
815893SN/A                        Mangled mangled (ConstString(mangled_cstr), true);
816893SN/A                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
817893SN/A                        if (mangled.GetDemangledName())
818893SN/A                            func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
819893SN/A                    }
820893SN/A                }
821893SN/A            }
822893SN/A            break;
823893SN/A
824893SN/A        case DW_TAG_inlined_subroutine:
825893SN/A            if (has_address)
826893SN/A            {
827893SN/A                if (name)
828893SN/A                    func_basenames.Insert (ConstString(name), die.GetOffset());
829893SN/A                if (mangled_cstr)
830893SN/A                {
831893SN/A                    // Make sure our mangled name isn't the same string table entry
832893SN/A                    // as our name. If it starts with '_', then it is ok, else compare
833893SN/A                    // the string to make sure it isn't the same and we don't end up
83414168Sredestad                    // with duplicate entries
835893SN/A                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
836893SN/A                    {
837893SN/A                        Mangled mangled (ConstString(mangled_cstr), true);
838893SN/A                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
839893SN/A                        if (mangled.GetDemangledName())
840893SN/A                            func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
841893SN/A                    }
842893SN/A                }
843893SN/A                else
844893SN/A                    func_fullnames.Insert (ConstString(name), die.GetOffset());
845893SN/A            }
846893SN/A            break;
847893SN/A
848893SN/A        case DW_TAG_base_type:
849893SN/A        case DW_TAG_class_type:
850893SN/A        case DW_TAG_constant:
851893SN/A        case DW_TAG_enumeration_type:
852893SN/A        case DW_TAG_string_type:
853893SN/A        case DW_TAG_subroutine_type:
854893SN/A        case DW_TAG_structure_type:
855893SN/A        case DW_TAG_union_type:
856893SN/A        case DW_TAG_typedef:
857893SN/A        case DW_TAG_unspecified_type:
858893SN/A            if (name && is_declaration == false)
859893SN/A            {
860893SN/A                types.Insert (ConstString(name), die.GetOffset());
861893SN/A            }
862893SN/A            break;
863893SN/A
864893SN/A        case DW_TAG_namespace:
865893SN/A            if (name)
866893SN/A                namespaces.Insert (ConstString(name), die.GetOffset());
867893SN/A            break;
868893SN/A
869893SN/A        case DW_TAG_variable:
870893SN/A            if (name && has_location && is_global_or_static_variable)
871893SN/A            {
872893SN/A                globals.Insert (ConstString(name), die.GetOffset());
873893SN/A                // Be sure to include variables by their mangled and demangled
874893SN/A                // names if they have any since a variable can have a basename
875893SN/A                // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
876893SN/A                // mangled name "(anonymous namespace)::i"...
877893SN/A
878893SN/A                // Make sure our mangled name isn't the same string table entry
879893SN/A                // as our name. If it starts with '_', then it is ok, else compare
880893SN/A                // the string to make sure it isn't the same and we don't end up
881893SN/A                // with duplicate entries
882893SN/A                if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
883893SN/A                {
884893SN/A                    Mangled mangled (ConstString(mangled_cstr), true);
885893SN/A                    globals.Insert (mangled.GetMangledName(), die.GetOffset());
886893SN/A                    if (mangled.GetDemangledName())
887893SN/A                        globals.Insert (mangled.GetDemangledName(), die.GetOffset());
888893SN/A                }
8893899SN/A            }
890893SN/A            break;
8913899SN/A
892893SN/A        default:
893893SN/A            continue;
894893SN/A        }
895893SN/A    }
896893SN/A}
897893SN/A
898893SN/Abool
899893SN/ADWARFCompileUnit::Supports_unnamed_objc_bitfields ()
900893SN/A{
901893SN/A    if (GetProducer() == eProducerClang)
902893SN/A    {
903893SN/A        const uint32_t major_version = GetProducerVersionMajor();
904893SN/A        if (major_version > 425 || (major_version == 425 && GetProducerVersionUpdate() >= 13))
905893SN/A            return true;
906893SN/A        else
907893SN/A            return false;
908893SN/A    }
909893SN/A    return true; // Assume all other compilers didn't have incorrect ObjC bitfield info
910893SN/A}
911893SN/A
912893SN/Abool
913893SN/ADWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type ()
914893SN/A{
915893SN/A    if (GetProducer() == eProducerLLVMGCC)
916893SN/A        return false;
917893SN/A    return true;
91814643Salanb}
919893SN/A
920893SN/Abool
921893SN/ADWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid()
922893SN/A{
923893SN/A    // llvm-gcc makes completely invalid decl file attributes and won't ever
924893SN/A    // be fixed, so we need to know to ignore these.
925893SN/A    return GetProducer() == eProducerLLVMGCC;
926893SN/A}
927893SN/A
928893SN/Avoid
929893SN/ADWARFCompileUnit::ParseProducerInfo ()
930893SN/A{
931893SN/A    m_producer_version_major = UINT32_MAX;
932893SN/A    m_producer_version_minor = UINT32_MAX;
933    m_producer_version_update = UINT32_MAX;
934
935    const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
936    if (die)
937    {
938
939        const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL);
940        if (producer_cstr)
941        {
942            RegularExpression llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$");
943            if (llvm_gcc_regex.Execute (producer_cstr))
944            {
945                m_producer = eProducerLLVMGCC;
946            }
947            else if (strstr(producer_cstr, "clang"))
948            {
949                static RegularExpression g_clang_version_regex("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)");
950                RegularExpression::Match regex_match(3);
951                if (g_clang_version_regex.Execute (producer_cstr, &regex_match))
952                {
953                    std::string str;
954                    if (regex_match.GetMatchAtIndex (producer_cstr, 1, str))
955                        m_producer_version_major = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
956                    if (regex_match.GetMatchAtIndex (producer_cstr, 2, str))
957                        m_producer_version_minor = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
958                    if (regex_match.GetMatchAtIndex (producer_cstr, 3, str))
959                        m_producer_version_update = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
960                }
961                m_producer = eProducerClang;
962            }
963            else if (strstr(producer_cstr, "GNU"))
964                m_producer = eProducerGCC;
965        }
966    }
967    if (m_producer == eProducerInvalid)
968        m_producer = eProcucerOther;
969}
970
971DWARFCompileUnit::Producer
972DWARFCompileUnit::GetProducer ()
973{
974    if (m_producer == eProducerInvalid)
975        ParseProducerInfo ();
976    return m_producer;
977}
978
979
980uint32_t
981DWARFCompileUnit::GetProducerVersionMajor()
982{
983    if (m_producer_version_major == 0)
984        ParseProducerInfo ();
985    return m_producer_version_major;
986}
987
988uint32_t
989DWARFCompileUnit::GetProducerVersionMinor()
990{
991    if (m_producer_version_minor == 0)
992        ParseProducerInfo ();
993    return m_producer_version_minor;
994}
995
996uint32_t
997DWARFCompileUnit::GetProducerVersionUpdate()
998{
999    if (m_producer_version_update == 0)
1000        ParseProducerInfo ();
1001    return m_producer_version_update;
1002}
1003
1004