DWARFDebugInfoEntry.cpp revision 0963fdd2478c6404d11b96e7d5ae1f2de8b3bb1f
1//===-- DWARFDebugInfoEntry.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 "DWARFDebugInfoEntry.h"
11
12#include <assert.h>
13
14#include <algorithm>
15
16#include "lldb/Core/Stream.h"
17#include "lldb/Expression/DWARFExpression.h"
18#include "lldb/Symbol/ObjectFile.h"
19
20#include "DWARFCompileUnit.h"
21#include "SymbolFileDWARF.h"
22#include "DWARFDebugAbbrev.h"
23#include "DWARFDebugAranges.h"
24#include "DWARFDebugInfo.h"
25#include "DWARFDIECollection.h"
26#include "DWARFFormValue.h"
27#include "DWARFLocationDescription.h"
28#include "DWARFLocationList.h"
29#include "DWARFDebugRanges.h"
30
31using namespace lldb_private;
32using namespace std;
33extern int g_verbose;
34
35
36
37DWARFDebugInfoEntry::Attributes::Attributes() :
38    m_infos()
39{
40}
41
42DWARFDebugInfoEntry::Attributes::~Attributes()
43{
44}
45
46
47uint32_t
48DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const
49{
50    collection::const_iterator end = m_infos.end();
51    collection::const_iterator beg = m_infos.begin();
52    collection::const_iterator pos;
53    for (pos = beg; pos != end; ++pos)
54    {
55        if (pos->attr == attr)
56            return std::distance(beg, pos);
57    }
58    return UINT32_MAX;
59}
60
61void
62DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
63{
64    Info info = { cu, attr_die_offset, attr, form };
65    m_infos.push_back(info);
66}
67
68bool
69DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
70{
71    return FindAttributeIndex(attr) != UINT32_MAX;
72}
73
74bool
75DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
76{
77    uint32_t attr_index = FindAttributeIndex(attr);
78    if (attr_index != UINT32_MAX)
79    {
80        m_infos.erase(m_infos.begin() + attr_index);
81        return true;
82    }
83    return false;
84}
85
86bool
87DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
88{
89    form_value.SetForm(FormAtIndex(i));
90    dw_offset_t offset = DIEOffsetAtIndex(i);
91    return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset, CompileUnitAtIndex(i));
92}
93
94uint64_t
95DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const
96{
97    DWARFFormValue form_value;
98    if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
99        return form_value.Reference(CompileUnitAtIndex(i));
100    return fail_value;
101}
102
103
104
105bool
106DWARFDebugInfoEntry::FastExtract
107(
108    const DataExtractor& debug_info_data,
109    const DWARFCompileUnit* cu,
110    const uint8_t *fixed_form_sizes,
111    uint32_t* offset_ptr
112)
113{
114    m_offset = *offset_ptr;
115
116    uint64_t abbr_idx = debug_info_data.GetULEB128 (offset_ptr);
117    assert (abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
118    m_abbr_idx = abbr_idx;
119
120    assert (fixed_form_sizes);  // For best performance this should be specified!
121
122    if (m_abbr_idx)
123    {
124        uint32_t offset = *offset_ptr;
125
126        const DWARFAbbreviationDeclaration *abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(m_abbr_idx);
127
128        m_tag = abbrevDecl->Tag();
129        m_has_children = abbrevDecl->HasChildren();
130        // Skip all data in the .debug_info for the attributes
131        const uint32_t numAttributes = abbrevDecl->NumAttributes();
132        register uint32_t i;
133        register dw_form_t form;
134        for (i=0; i<numAttributes; ++i)
135        {
136            form = abbrevDecl->GetFormByIndexUnchecked(i);
137
138            const uint8_t fixed_skip_size = fixed_form_sizes [form];
139            if (fixed_skip_size)
140                offset += fixed_skip_size;
141            else
142            {
143                bool form_is_indirect = false;
144                do
145                {
146                    form_is_indirect = false;
147                    register uint32_t form_size = 0;
148                    switch (form)
149                    {
150                    // Blocks if inlined data that have a length field and the data bytes
151                    // inlined in the .debug_info
152                    case DW_FORM_block      : form_size = debug_info_data.GetULEB128 (&offset);      break;
153                    case DW_FORM_block1     : form_size = debug_info_data.GetU8_unchecked (&offset); break;
154                    case DW_FORM_block2     : form_size = debug_info_data.GetU16_unchecked (&offset);break;
155                    case DW_FORM_block4     : form_size = debug_info_data.GetU32_unchecked (&offset);break;
156
157                    // Inlined NULL terminated C-strings
158                    case DW_FORM_string     :
159                        debug_info_data.GetCStr (&offset);
160                        break;
161
162                    // Compile unit address sized values
163                    case DW_FORM_addr       :
164                    case DW_FORM_ref_addr   :
165                        form_size = cu->GetAddressByteSize();
166                        break;
167
168                    // 1 byte values
169                    case DW_FORM_data1      :
170                    case DW_FORM_flag       :
171                    case DW_FORM_ref1       :
172                        form_size = 1;
173                        break;
174
175                    // 2 byte values
176                    case DW_FORM_data2      :
177                    case DW_FORM_ref2       :
178                        form_size = 2;
179                        break;
180
181                    // 4 byte values
182                    case DW_FORM_strp       :
183                    case DW_FORM_data4      :
184                    case DW_FORM_ref4       :
185                        form_size = 4;
186                        break;
187
188                    // 8 byte values
189                    case DW_FORM_data8      :
190                    case DW_FORM_ref8       :
191                        form_size = 8;
192                        break;
193
194                    // signed or unsigned LEB 128 values
195                    case DW_FORM_sdata      :
196                    case DW_FORM_udata      :
197                    case DW_FORM_ref_udata  :
198                        debug_info_data.Skip_LEB128 (&offset);
199                        break;
200
201                    case DW_FORM_indirect   :
202                        form_is_indirect = true;
203                        form = debug_info_data.GetULEB128 (&offset);
204                        break;
205
206                    default:
207                        *offset_ptr = m_offset;
208                        return false;
209                    }
210                    offset += form_size;
211
212                } while (form_is_indirect);
213            }
214        }
215        *offset_ptr = offset;
216        return true;
217    }
218    else
219    {
220        m_tag = 0;
221        m_has_children = false;
222        return true;    // NULL debug tag entry
223    }
224
225    return false;
226}
227
228//----------------------------------------------------------------------
229// Extract
230//
231// Extract a debug info entry for a given compile unit from the
232// .debug_info and .debug_abbrev data within the SymbolFileDWARF class
233// starting at the given offset
234//----------------------------------------------------------------------
235bool
236DWARFDebugInfoEntry::Extract
237(
238    SymbolFileDWARF* dwarf2Data,
239    const DWARFCompileUnit* cu,
240    uint32_t* offset_ptr
241)
242{
243    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
244//    const DataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
245    const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
246    const uint8_t cu_addr_size = cu->GetAddressByteSize();
247    uint32_t offset = *offset_ptr;
248//  if (offset >= cu_end_offset)
249//      Log::Error("DIE at offset 0x%8.8x is beyond the end of the current compile unit (0x%8.8x)", m_offset, cu_end_offset);
250    if ((offset < cu_end_offset) && debug_info_data.ValidOffset(offset))
251    {
252        m_offset = offset;
253
254        const uint64_t abbr_idx = debug_info_data.GetULEB128(&offset);
255        assert (abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
256        m_abbr_idx = abbr_idx;
257        if (abbr_idx)
258        {
259            const DWARFAbbreviationDeclaration *abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(abbr_idx);
260
261            if (abbrevDecl)
262            {
263                m_tag = abbrevDecl->Tag();
264                m_has_children = abbrevDecl->HasChildren();
265
266                bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
267                if (cu && isCompileUnitTag)
268                    ((DWARFCompileUnit*)cu)->SetBaseAddress(0);
269
270                // Skip all data in the .debug_info for the attributes
271                const uint32_t numAttributes = abbrevDecl->NumAttributes();
272                uint32_t i;
273                dw_attr_t attr;
274                dw_form_t form;
275                for (i=0; i<numAttributes; ++i)
276                {
277                    abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
278
279                    if (isCompileUnitTag && ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc)))
280                    {
281                        DWARFFormValue form_value(form);
282                        if (form_value.ExtractValue(debug_info_data, &offset, cu))
283                        {
284                            if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
285                                ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
286                        }
287                    }
288                    else
289                    {
290                        bool form_is_indirect = false;
291                        do
292                        {
293                            form_is_indirect = false;
294                            register uint32_t form_size = 0;
295                            switch (form)
296                            {
297                            // Blocks if inlined data that have a length field and the data bytes
298                            // inlined in the .debug_info
299                            case DW_FORM_block      : form_size = debug_info_data.GetULEB128(&offset);  break;
300                            case DW_FORM_block1     : form_size = debug_info_data.GetU8(&offset);       break;
301                            case DW_FORM_block2     : form_size = debug_info_data.GetU16(&offset);      break;
302                            case DW_FORM_block4     : form_size = debug_info_data.GetU32(&offset);      break;
303
304                            // Inlined NULL terminated C-strings
305                            case DW_FORM_string     : debug_info_data.GetCStr(&offset);                 break;
306
307                            // Compile unit address sized values
308                            case DW_FORM_addr       :
309                            case DW_FORM_ref_addr   :
310                                form_size = cu_addr_size;
311                                break;
312
313                            // 1 byte values
314                            case DW_FORM_data1      :
315                            case DW_FORM_flag       :
316                            case DW_FORM_ref1       :
317                                form_size = 1;
318                                break;
319
320                            // 2 byte values
321                            case DW_FORM_data2      :
322                            case DW_FORM_ref2       :
323                                form_size = 2;
324                                break;
325
326                            // 4 byte values
327                            case DW_FORM_strp       :
328                                form_size = 4;
329                                break;
330
331                            case DW_FORM_data4      :
332                            case DW_FORM_ref4       :
333                                form_size = 4;
334                                break;
335
336                            // 8 byte values
337                            case DW_FORM_data8      :
338                            case DW_FORM_ref8       :
339                                form_size = 8;
340                                break;
341
342                            // signed or unsigned LEB 128 values
343                            case DW_FORM_sdata      :
344                            case DW_FORM_udata      :
345                            case DW_FORM_ref_udata  :
346                                debug_info_data.Skip_LEB128(&offset);
347                                break;
348
349                            case DW_FORM_indirect   :
350                                form = debug_info_data.GetULEB128(&offset);
351                                form_is_indirect = true;
352                                break;
353
354                            default:
355                                *offset_ptr = offset;
356                                return false;
357                            }
358
359                            offset += form_size;
360                        } while (form_is_indirect);
361                    }
362                }
363                *offset_ptr = offset;
364                return true;
365            }
366        }
367        else
368        {
369            m_tag = 0;
370            m_has_children = false;
371            *offset_ptr = offset;
372            return true;    // NULL debug tag entry
373        }
374    }
375
376    return false;
377}
378
379//----------------------------------------------------------------------
380// DumpAncestry
381//
382// Dumps all of a debug information entries parents up until oldest and
383// all of it's attributes to the specified stream.
384//----------------------------------------------------------------------
385void
386DWARFDebugInfoEntry::DumpAncestry
387(
388    SymbolFileDWARF* dwarf2Data,
389    const DWARFCompileUnit* cu,
390    const DWARFDebugInfoEntry* oldest,
391    Stream &s,
392    uint32_t recurse_depth
393) const
394{
395    const DWARFDebugInfoEntry* parent = GetParent();
396    if (parent && parent != oldest)
397        parent->DumpAncestry(dwarf2Data, cu, oldest, s, 0);
398    Dump(dwarf2Data, cu, s, recurse_depth);
399}
400
401//----------------------------------------------------------------------
402// Compare two DIE by comparing all their attributes values, and
403// following all DW_FORM_ref attributes and comparing their contents as
404// well (except for DW_AT_sibling attributes.
405//
406//  DWARFDebugInfoEntry::CompareState compare_state;
407//  int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true);
408//----------------------------------------------------------------------
409//int
410//DWARFDebugInfoEntry::Compare
411//(
412//    SymbolFileDWARF* dwarf2Data,
413//    dw_offset_t a_die_offset,
414//    dw_offset_t b_die_offset,
415//    CompareState &compare_state,
416//    bool compare_siblings,
417//    bool compare_children
418//)
419//{
420//    if (a_die_offset == b_die_offset)
421//        return 0;
422//
423//    DWARFCompileUnitSP a_cu_sp;
424//    DWARFCompileUnitSP b_cu_sp;
425//    const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp);
426//    const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp);
427//
428//    return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children);
429//}
430//
431//int
432//DWARFDebugInfoEntry::Compare
433//(
434//    SymbolFileDWARF* dwarf2Data,
435//    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
436//    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
437//    CompareState &compare_state,
438//    bool compare_siblings,
439//    bool compare_children
440//)
441//{
442//    if (a_die == b_die)
443//        return 0;
444//
445//    if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset()))
446//    {
447//        // We are already comparing both of these types, so let
448//        // compares complete for the real result
449//        return 0;
450//    }
451//
452//    //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset());
453//
454//    // Do we have two valid DIEs?
455//    if (a_die && b_die)
456//    {
457//        // Both DIE are valid
458//        int result = 0;
459//
460//        const dw_tag_t a_tag = a_die->Tag();
461//        const dw_tag_t b_tag = b_die->Tag();
462//        if (a_tag == 0 && b_tag == 0)
463//            return 0;
464//
465//        //printf("    comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag));
466//
467//        if (a_tag < b_tag)
468//            return -1;
469//        else if (a_tag > b_tag)
470//            return 1;
471//
472//        DWARFDebugInfoEntry::Attributes a_attrs;
473//        DWARFDebugInfoEntry::Attributes b_attrs;
474//        size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs);
475//        size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs);
476//        if (a_attr_count != b_attr_count)
477//        {
478//            a_attrs.RemoveAttribute(DW_AT_sibling);
479//            b_attrs.RemoveAttribute(DW_AT_sibling);
480//        }
481//
482//        a_attr_count = a_attrs.Size();
483//        b_attr_count = b_attrs.Size();
484//
485//        DWARFFormValue a_form_value;
486//        DWARFFormValue b_form_value;
487//
488//        if (a_attr_count != b_attr_count)
489//        {
490//            uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration);
491//            uint32_t a_name_index = UINT32_MAX;
492//            uint32_t b_name_index = UINT32_MAX;
493//            if (is_decl_index != UINT32_MAX)
494//            {
495//                if (a_attr_count == 2)
496//                {
497//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
498//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
499//                }
500//            }
501//            else
502//            {
503//                is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration);
504//                if (is_decl_index != UINT32_MAX && a_attr_count == 2)
505//                {
506//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
507//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
508//                }
509//            }
510//            if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX)
511//            {
512//                if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) &&
513//                    b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value))
514//                {
515//                    result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data());
516//                    if (result == 0)
517//                    {
518//                        a_attr_count = b_attr_count = 0;
519//                        compare_children = false;
520//                    }
521//                }
522//            }
523//        }
524//
525//        if (a_attr_count < b_attr_count)
526//            return -1;
527//        if (a_attr_count > b_attr_count)
528//            return 1;
529//
530//
531//        // The number of attributes are the same...
532//        if (a_attr_count > 0)
533//        {
534//            const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
535//
536//            uint32_t i;
537//            for (i=0; i<a_attr_count; ++i)
538//            {
539//                const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i);
540//                const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i);
541//                //printf("    comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n",
542//                //                a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr),
543//                //                b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr));
544//
545//                if (a_attr < b_attr)
546//                    return -1;
547//                else if (a_attr > b_attr)
548//                    return 1;
549//
550//                switch (a_attr)
551//                {
552//                // Since we call a form of GetAttributes which inlines the
553//                // attributes from DW_AT_abstract_origin and DW_AT_specification
554//                // we don't care if their values mismatch...
555//                case DW_AT_abstract_origin:
556//                case DW_AT_specification:
557//                case DW_AT_sibling:
558//                case DW_AT_containing_type:
559//                    //printf("        action = IGNORE\n");
560//                    result = 0;
561//                    break;  // ignore
562//
563//                default:
564//                    if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) &&
565//                        b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value))
566//                        result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr);
567//                    break;
568//                }
569//
570//                //printf("\t  result = %i\n", result);
571//
572//                if (result != 0)
573//                {
574//                    // Attributes weren't equal, lets see if we care?
575//                    switch (a_attr)
576//                    {
577//                    case DW_AT_decl_file:
578//                        // TODO: add the ability to compare files in two different compile units
579//                        if (a_cu == b_cu)
580//                        {
581//                            //printf("        action = RETURN RESULT\n");
582//                            return result;  // Only return the compare results when the compile units are the same and the decl_file attributes can be compared
583//                        }
584//                        else
585//                        {
586//                            result = 0;
587//                            //printf("        action = IGNORE\n");
588//                        }
589//                        break;
590//
591//                    default:
592//                        switch (a_attrs.FormAtIndex(i))
593//                        {
594//                        case DW_FORM_ref1:
595//                        case DW_FORM_ref2:
596//                        case DW_FORM_ref4:
597//                        case DW_FORM_ref8:
598//                        case DW_FORM_ref_udata:
599//                        case DW_FORM_ref_addr:
600//                            //printf("    action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu));
601//                            // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets...
602//                            result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true);
603//                            if (result != 0)
604//                                return result;
605//                            break;
606//
607//                        default:
608//                            // We do care that they were different, return this result...
609//                            //printf("        action = RETURN RESULT\n");
610//                            return result;
611//                        }
612//                    }
613//                }
614//            }
615//        }
616//        //printf("    SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag));
617//
618//        if (compare_children)
619//        {
620//            bool a_has_children = a_die->HasChildren();
621//            bool b_has_children = b_die->HasChildren();
622//            if (a_has_children == b_has_children)
623//            {
624//                // Both either have kids or don't
625//                if (a_has_children)
626//                    result = Compare(   dwarf2Data,
627//                                        a_cu, a_die->GetFirstChild(),
628//                                        b_cu, b_die->GetFirstChild(),
629//                                        compare_state, true, compare_children);
630//                else
631//                    result = 0;
632//            }
633//            else if (!a_has_children)
634//                result = -1;    // A doesn't have kids, but B does
635//            else
636//                result = 1; // A has kids, but B doesn't
637//        }
638//
639//        if (compare_siblings)
640//        {
641//            result = Compare(   dwarf2Data,
642//                                a_cu, a_die->GetSibling(),
643//                                b_cu, b_die->GetSibling(),
644//                                compare_state, true, compare_children);
645//        }
646//
647//        return result;
648//    }
649//
650//    if (a_die == NULL)
651//        return -1;  // a_die is NULL, yet b_die is non-NULL
652//    else
653//        return 1;   // a_die is non-NULL, yet b_die is NULL
654//
655//}
656//
657//
658//int
659//DWARFDebugInfoEntry::Compare
660//(
661//  SymbolFileDWARF* dwarf2Data,
662//  const DWARFCompileUnit* cu_a,
663//  const DWARFDebugInfoEntry* die_a,
664//  const DWARFCompileUnit* cu_a,
665//  const DWARFDebugInfoEntry* die_b,
666//  CompareState &compare_state
667//)
668//{
669//}
670
671//----------------------------------------------------------------------
672// GetDIENamesAndRanges
673//
674// Gets the valid address ranges for a given DIE by looking for a
675// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges
676// attributes.
677//----------------------------------------------------------------------
678bool
679DWARFDebugInfoEntry::GetDIENamesAndRanges
680(
681    SymbolFileDWARF* dwarf2Data,
682    const DWARFCompileUnit* cu,
683    const char * &name,
684    const char * &mangled,
685    DWARFDebugRanges::RangeList& ranges,
686    int& decl_file,
687    int& decl_line,
688    int& decl_column,
689    int& call_file,
690    int& call_line,
691    int& call_column,
692    DWARFExpression *frame_base
693) const
694{
695    if (dwarf2Data == NULL)
696        return false;
697
698    dw_addr_t lo_pc = DW_INVALID_ADDRESS;
699    dw_addr_t hi_pc = DW_INVALID_ADDRESS;
700    std::vector<dw_offset_t> die_offsets;
701    bool set_frame_base_loclist_addr = false;
702
703    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu);
704
705    if (abbrevDecl)
706    {
707        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
708        uint32_t offset = m_offset;
709
710        if (!debug_info_data.ValidOffset(offset))
711            return false;
712
713        // Skip the abbreviation code
714        debug_info_data.Skip_LEB128(&offset);
715
716        const uint32_t numAttributes = abbrevDecl->NumAttributes();
717        uint32_t i;
718        dw_attr_t attr;
719        dw_form_t form;
720        for (i=0; i<numAttributes; ++i)
721        {
722            abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
723            DWARFFormValue form_value(form);
724            if (form_value.ExtractValue(debug_info_data, &offset, cu))
725            {
726                switch (attr)
727                {
728                case DW_AT_low_pc:
729                case DW_AT_entry_pc:
730                    lo_pc = form_value.Unsigned();
731                    break;
732
733                case DW_AT_high_pc:
734                    hi_pc = form_value.Unsigned();
735                    break;
736
737                case DW_AT_ranges:
738                    {
739                        const DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
740                        debug_ranges->FindRanges(form_value.Unsigned(), ranges);
741                        // All DW_AT_ranges are relative to the base address of the
742                        // compile unit. We add the compile unit base address to make
743                        // sure all the addresses are properly fixed up.
744                        ranges.Slide(cu->GetBaseAddress());
745                    }
746                    break;
747
748                case DW_AT_name:
749                    if (name == NULL)
750                        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
751                    break;
752
753                case DW_AT_MIPS_linkage_name:
754                    if (mangled == NULL)
755                        mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
756                    break;
757
758                case DW_AT_abstract_origin:
759                    die_offsets.push_back(form_value.Reference(cu));
760                    break;
761
762                case DW_AT_specification:
763                    die_offsets.push_back(form_value.Reference(cu));
764                    break;
765
766                case DW_AT_decl_file:
767                    if (decl_file == 0)
768                        decl_file = form_value.Unsigned();
769                    break;
770
771                case DW_AT_decl_line:
772                    if (decl_line == 0)
773                        decl_line = form_value.Unsigned();
774                    break;
775
776                case DW_AT_decl_column:
777                    if (decl_column == 0)
778                        decl_column = form_value.Unsigned();
779                    break;
780
781                case DW_AT_call_file:
782                    if (call_file == 0)
783                        call_file = form_value.Unsigned();
784                    break;
785
786                case DW_AT_call_line:
787                    if (call_line == 0)
788                        call_line = form_value.Unsigned();
789                    break;
790
791                case DW_AT_call_column:
792                    if (call_column == 0)
793                        call_column = form_value.Unsigned();
794                    break;
795
796                case DW_AT_frame_base:
797                    if (frame_base)
798                    {
799                        if (form_value.BlockData())
800                        {
801                            uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
802                            uint32_t block_length = form_value.Unsigned();
803                            frame_base->SetOpcodeData(debug_info_data, block_offset, block_length);
804                        }
805                        else
806                        {
807                            const DataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
808                            const dw_offset_t debug_loc_offset = form_value.Unsigned();
809
810                            size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
811                            if (loc_list_length > 0)
812                            {
813                                frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
814                                if (lo_pc != DW_INVALID_ADDRESS)
815                                {
816                                    assert (lo_pc >= cu->GetBaseAddress());
817                                    frame_base->SetLocationListSlide(lo_pc - cu->GetBaseAddress());
818                                }
819                                else
820                                {
821                                    set_frame_base_loclist_addr = true;
822                                }
823                            }
824                        }
825                    }
826                    break;
827
828                default:
829                    break;
830                }
831            }
832        }
833    }
834
835    if (ranges.IsEmpty())
836    {
837        if (lo_pc != DW_INVALID_ADDRESS)
838        {
839            if (hi_pc != DW_INVALID_ADDRESS && hi_pc > lo_pc)
840                ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc));
841            else
842                ranges.Append(DWARFDebugRanges::Range (lo_pc, 0));
843        }
844    }
845
846    if (set_frame_base_loclist_addr)
847    {
848        dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
849        assert (lowest_range_pc >= cu->GetBaseAddress());
850        frame_base->SetLocationListSlide (lowest_range_pc - cu->GetBaseAddress());
851    }
852
853    if (ranges.IsEmpty() || name == NULL || mangled == NULL)
854    {
855        std::vector<dw_offset_t>::const_iterator pos;
856        std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
857        for (pos = die_offsets.begin(); pos != end; ++pos)
858        {
859            DWARFCompileUnitSP cu_sp_ptr;
860            const DWARFDebugInfoEntry* die = NULL;
861            dw_offset_t die_offset = *pos;
862            if (die_offset != DW_INVALID_OFFSET)
863            {
864                die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
865                if (die)
866                    die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
867            }
868        }
869    }
870    return !ranges.IsEmpty();
871}
872
873//----------------------------------------------------------------------
874// Dump
875//
876// Dumps a debug information entry and all of it's attributes to the
877// specified stream.
878//----------------------------------------------------------------------
879void
880DWARFDebugInfoEntry::Dump
881(
882    SymbolFileDWARF* dwarf2Data,
883    const DWARFCompileUnit* cu,
884    Stream &s,
885    uint32_t recurse_depth
886) const
887{
888    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
889    uint32_t offset = m_offset;
890
891    if (debug_info_data.ValidOffset(offset))
892    {
893        dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset);
894
895        s.Printf("\n0x%8.8x: ", m_offset);
896        s.Indent();
897        if (abbrCode)
898        {
899            const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu);
900
901            if (abbrevDecl)
902            {
903                s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag()));
904                s.Printf( " [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*':' ');
905
906                // Dump all data in the .debug_info for the attributes
907                const uint32_t numAttributes = abbrevDecl->NumAttributes();
908                uint32_t i;
909                dw_attr_t attr;
910                dw_form_t form;
911                for (i=0; i<numAttributes; ++i)
912                {
913                    abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
914
915                    DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, form);
916                }
917
918                const DWARFDebugInfoEntry* child = GetFirstChild();
919                if (recurse_depth > 0 && child)
920                {
921                    s.IndentMore();
922
923                    while (child)
924                    {
925                        child->Dump(dwarf2Data, cu, s, recurse_depth-1);
926                        child = child->GetSibling();
927                    }
928                    s.IndentLess();
929                }
930            }
931            else
932                s.Printf( "Abbreviation code note found in 'debug_abbrev' class for code: %u\n", abbrCode);
933        }
934        else
935        {
936            s.Printf( "NULL\n");
937        }
938    }
939}
940
941void
942DWARFDebugInfoEntry::DumpLocation
943(
944    SymbolFileDWARF* dwarf2Data,
945    DWARFCompileUnit* cu,
946    Stream &s
947) const
948{
949    const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly();
950    const char *cu_name = NULL;
951    if (cu_die != NULL)
952        cu_name = cu_die->GetName (dwarf2Data, cu);
953    const char *obj_file_name = NULL;
954    ObjectFile *obj_file = dwarf2Data->GetObjectFile();
955    if (obj_file)
956        obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString();
957    const char *die_name = GetName (dwarf2Data, cu);
958    s.Printf ("0x%8.8x/0x%8.8x: %-30s (from %s in %s)",
959              cu->GetOffset(),
960              GetOffset(),
961              die_name ? die_name : "",
962              cu_name ? cu_name : "<NULL>",
963              obj_file_name ? obj_file_name : "<NULL>");
964}
965
966//----------------------------------------------------------------------
967// DumpAttribute
968//
969// Dumps a debug information entry attribute along with it's form. Any
970// special display of attributes is done (disassemble location lists,
971// show enumeration values for attributes, etc).
972//----------------------------------------------------------------------
973void
974DWARFDebugInfoEntry::DumpAttribute
975(
976    SymbolFileDWARF* dwarf2Data,
977    const DWARFCompileUnit* cu,
978    const DataExtractor& debug_info_data,
979    uint32_t* offset_ptr,
980    Stream &s,
981    dw_attr_t attr,
982    dw_form_t form
983)
984{
985    bool verbose    = s.GetVerbose();
986    bool show_form  = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
987    const DataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
988    if (verbose)
989        s.Offset (*offset_ptr);
990    else
991        s.Printf ("            ");
992    s.Indent(DW_AT_value_to_name(attr));
993
994    if (show_form)
995    {
996        s.Printf( "[%s", DW_FORM_value_to_name(form));
997    }
998
999    DWARFFormValue form_value(form);
1000
1001    if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu))
1002        return;
1003
1004    if (show_form)
1005    {
1006        if (form == DW_FORM_indirect)
1007        {
1008            s.Printf( " [%s]", DW_FORM_value_to_name(form_value.Form()));
1009        }
1010
1011        s.PutCString("] ");
1012    }
1013
1014    s.PutCString("( ");
1015
1016    // Always dump form value if verbose is enabled
1017    if (verbose)
1018    {
1019        form_value.Dump(s, debug_str_data, cu);
1020    }
1021
1022
1023    // Check to see if we have any special attribute formatters
1024    switch (attr)
1025    {
1026    case DW_AT_stmt_list:
1027        if ( verbose ) s.PutCString(" ( ");
1028        s.Printf( "0x%8.8llx", form_value.Unsigned());
1029        if ( verbose ) s.PutCString(" )");
1030        break;
1031
1032    case DW_AT_language:
1033        if ( verbose ) s.PutCString(" ( ");
1034        s.PutCString(DW_LANG_value_to_name(form_value.Unsigned()));
1035        if ( verbose ) s.PutCString(" )");
1036        break;
1037
1038    case DW_AT_encoding:
1039        if ( verbose ) s.PutCString(" ( ");
1040        s.PutCString(DW_ATE_value_to_name(form_value.Unsigned()));
1041        if ( verbose ) s.PutCString(" )");
1042        break;
1043
1044    case DW_AT_frame_base:
1045    case DW_AT_location:
1046    case DW_AT_data_member_location:
1047        {
1048            const uint8_t* blockData = form_value.BlockData();
1049            if (blockData)
1050            {
1051                if (!verbose)
1052                    form_value.Dump(s, debug_str_data, cu);
1053
1054                // Location description is inlined in data in the form value
1055                DataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
1056                if ( verbose ) s.PutCString(" ( ");
1057                print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
1058                if ( verbose ) s.PutCString(" )");
1059            }
1060            else
1061            {
1062                // We have a location list offset as the value that is
1063                // the offset into the .debug_loc section that describes
1064                // the value over it's lifetime
1065                uint64_t debug_loc_offset = form_value.Unsigned();
1066                if (dwarf2Data)
1067                {
1068                    if ( !verbose )
1069                        form_value.Dump(s, debug_str_data, cu);
1070                    DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
1071                }
1072                else
1073                {
1074                    if ( !verbose )
1075                        form_value.Dump(s, NULL, cu);
1076                }
1077            }
1078        }
1079        break;
1080
1081    case DW_AT_abstract_origin:
1082    case DW_AT_specification:
1083        {
1084            uint64_t abstract_die_offset = form_value.Reference(cu);
1085            form_value.Dump(s, debug_str_data, cu);
1086        //  *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
1087            if ( verbose ) s.PutCString(" ( ");
1088            GetName(dwarf2Data, cu, abstract_die_offset, s);
1089            if ( verbose ) s.PutCString(" )");
1090        }
1091        break;
1092
1093    case DW_AT_type:
1094        {
1095            uint64_t type_die_offset = form_value.Reference(cu);
1096            if (!verbose)
1097                form_value.Dump(s, debug_str_data, cu);
1098            s.PutCString(" ( ");
1099            AppendTypeName(dwarf2Data, cu, type_die_offset, s);
1100            s.PutCString(" )");
1101        }
1102        break;
1103
1104    case DW_AT_ranges:
1105        {
1106            if ( !verbose )
1107                form_value.Dump(s, debug_str_data, cu);
1108            uint32_t ranges_offset = form_value.Unsigned();
1109            dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
1110            DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), &ranges_offset, base_addr);
1111        }
1112        break;
1113
1114    default:
1115        if ( !verbose )
1116            form_value.Dump(s, debug_str_data, cu);
1117        break;
1118    }
1119
1120    s.PutCString(" )\n");
1121}
1122
1123//----------------------------------------------------------------------
1124// Get all attribute values for a given DIE, including following any
1125// specification or abstract origin attributes and including those in
1126// the results. Any duplicate attributes will have the first instance
1127// take precedence (this can happen for declaration attributes).
1128//----------------------------------------------------------------------
1129size_t
1130DWARFDebugInfoEntry::GetAttributes
1131(
1132    SymbolFileDWARF* dwarf2Data,
1133    const DWARFCompileUnit* cu,
1134    const uint8_t *fixed_form_sizes,
1135    DWARFDebugInfoEntry::Attributes& attributes,
1136    uint32_t curr_depth
1137) const
1138{
1139    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu);
1140
1141    if (abbrevDecl)
1142    {
1143        if (fixed_form_sizes == NULL)
1144            fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize());
1145        uint32_t offset = GetOffset();
1146        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
1147
1148        // Skip the abbreviation code so we are at the data for the attributes
1149        debug_info_data.Skip_LEB128(&offset);
1150
1151        const uint32_t num_attributes = abbrevDecl->NumAttributes();
1152        uint32_t i;
1153        dw_attr_t attr;
1154        dw_form_t form;
1155        DWARFFormValue form_value;
1156        for (i=0; i<num_attributes; ++i)
1157        {
1158            abbrevDecl->GetAttrAndFormByIndexUnchecked (i, attr, form);
1159
1160            // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
1161            // attributes, the depth will be non-zero. We need to omit certain
1162            // attributes that don't make sense.
1163            switch (attr)
1164            {
1165            case DW_AT_sibling:
1166            case DW_AT_declaration:
1167                if (curr_depth > 0)
1168                {
1169                    // This attribute doesn't make sense when combined with
1170                    // the DIE that references this DIE. We know a DIE is
1171                    // referencing this DIE because curr_depth is not zero
1172                    break;
1173                }
1174                // Fall through...
1175            default:
1176                attributes.Append(cu, offset, attr, form);
1177                break;
1178            }
1179
1180            if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))
1181            {
1182                form_value.SetForm(form);
1183                if (form_value.ExtractValue(debug_info_data, &offset, cu))
1184                {
1185                    const DWARFDebugInfoEntry* die = NULL;
1186                    dw_offset_t die_offset = form_value.Reference(cu);
1187                    if (cu->ContainsDIEOffset(die_offset))
1188                    {
1189                        die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
1190                        if (die)
1191                            die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1);
1192                    }
1193                    else
1194                    {
1195                        DWARFCompileUnitSP cu_sp_ptr;
1196                        die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
1197                        if (die)
1198                            die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1);
1199                    }
1200                }
1201            }
1202            else
1203            {
1204                const uint8_t fixed_skip_size = fixed_form_sizes [form];
1205                if (fixed_skip_size)
1206                    offset += fixed_skip_size;
1207                else
1208                    DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu);
1209            }
1210        }
1211    }
1212    else
1213    {
1214        attributes.Clear();
1215    }
1216    return attributes.Size();
1217
1218}
1219
1220//----------------------------------------------------------------------
1221// GetAttributeValue
1222//
1223// Get the value of an attribute and return the .debug_info offset of the
1224// attribute if it was properly extracted into form_value, or zero
1225// if we fail since an offset of zero is invalid for an attribute (it
1226// would be a compile unit header).
1227//----------------------------------------------------------------------
1228dw_offset_t
1229DWARFDebugInfoEntry::GetAttributeValue
1230(
1231    SymbolFileDWARF* dwarf2Data,
1232    const DWARFCompileUnit* cu,
1233    const dw_attr_t attr,
1234    DWARFFormValue& form_value,
1235    dw_offset_t* end_attr_offset_ptr
1236) const
1237{
1238    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu);
1239
1240    if (abbrevDecl)
1241    {
1242        uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
1243
1244        if (attr_idx != DW_INVALID_INDEX)
1245        {
1246            uint32_t offset = GetOffset();
1247
1248            const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
1249
1250            // Skip the abbreviation code so we are at the data for the attributes
1251            debug_info_data.Skip_LEB128(&offset);
1252
1253            uint32_t idx=0;
1254            while (idx<attr_idx)
1255                DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu);
1256
1257            const dw_offset_t attr_offset = offset;
1258            form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
1259            if (form_value.ExtractValue(debug_info_data, &offset, cu))
1260            {
1261                if (end_attr_offset_ptr)
1262                    *end_attr_offset_ptr = offset;
1263                return attr_offset;
1264            }
1265        }
1266    }
1267
1268    return 0;
1269}
1270
1271//----------------------------------------------------------------------
1272// GetAttributeValueAsString
1273//
1274// Get the value of an attribute as a string return it. The resulting
1275// pointer to the string data exists within the supplied SymbolFileDWARF
1276// and will only be available as long as the SymbolFileDWARF is still around
1277// and it's content doesn't change.
1278//----------------------------------------------------------------------
1279const char*
1280DWARFDebugInfoEntry::GetAttributeValueAsString
1281(
1282    SymbolFileDWARF* dwarf2Data,
1283    const DWARFCompileUnit* cu,
1284    const dw_attr_t attr,
1285    const char* fail_value) const
1286{
1287    DWARFFormValue form_value;
1288    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1289        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
1290    return fail_value;
1291}
1292
1293//----------------------------------------------------------------------
1294// GetAttributeValueAsUnsigned
1295//
1296// Get the value of an attribute as unsigned and return it.
1297//----------------------------------------------------------------------
1298uint64_t
1299DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
1300(
1301    SymbolFileDWARF* dwarf2Data,
1302    const DWARFCompileUnit* cu,
1303    const dw_attr_t attr,
1304    uint64_t fail_value
1305) const
1306{
1307    DWARFFormValue form_value;
1308    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1309        return form_value.Unsigned();
1310    return fail_value;
1311}
1312
1313//----------------------------------------------------------------------
1314// GetAttributeValueAsSigned
1315//
1316// Get the value of an attribute a signed value and return it.
1317//----------------------------------------------------------------------
1318int64_t
1319DWARFDebugInfoEntry::GetAttributeValueAsSigned
1320(
1321    SymbolFileDWARF* dwarf2Data,
1322    const DWARFCompileUnit* cu,
1323    const dw_attr_t attr,
1324    int64_t fail_value
1325) const
1326{
1327    DWARFFormValue form_value;
1328    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1329        return form_value.Signed();
1330    return fail_value;
1331}
1332
1333//----------------------------------------------------------------------
1334// GetAttributeValueAsReference
1335//
1336// Get the value of an attribute as reference and fix up and compile
1337// unit relative offsets as needed.
1338//----------------------------------------------------------------------
1339uint64_t
1340DWARFDebugInfoEntry::GetAttributeValueAsReference
1341(
1342    SymbolFileDWARF* dwarf2Data,
1343    const DWARFCompileUnit* cu,
1344    const dw_attr_t attr,
1345    uint64_t fail_value
1346) const
1347{
1348    DWARFFormValue form_value;
1349    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1350        return form_value.Reference(cu);
1351    return fail_value;
1352}
1353
1354//----------------------------------------------------------------------
1355// GetAttributeValueAsLocation
1356//
1357// Get the value of an attribute as reference and fix up and compile
1358// unit relative offsets as needed.
1359//----------------------------------------------------------------------
1360dw_offset_t
1361DWARFDebugInfoEntry::GetAttributeValueAsLocation
1362(
1363    SymbolFileDWARF* dwarf2Data,
1364    const DWARFCompileUnit* cu,
1365    const dw_attr_t attr,
1366    DataExtractor& location_data,
1367    uint32_t &block_size
1368) const
1369{
1370    block_size = 0;
1371    DWARFFormValue form_value;
1372
1373    // Empty out data in case we don't find anything
1374    location_data.Clear();
1375    dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
1376    const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
1377    if (attr_offset)
1378    {
1379        const uint8_t* blockData = form_value.BlockData();
1380        if (blockData)
1381        {
1382            // We have an inlined location list in the .debug_info section
1383            const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
1384            dw_offset_t block_offset = blockData - debug_info.GetDataStart();
1385            block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
1386            location_data.SetData(debug_info, block_offset, block_size);
1387        }
1388        else
1389        {
1390            // We have a location list offset as the value that is
1391            // the offset into the .debug_loc section that describes
1392            // the value over it's lifetime
1393            dw_offset_t debug_loc_offset = form_value.Unsigned();
1394            if (dwarf2Data)
1395            {
1396                assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
1397                return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
1398            }
1399        }
1400    }
1401    return attr_offset;
1402}
1403
1404//----------------------------------------------------------------------
1405// GetName
1406//
1407// Get value of the DW_AT_name attribute and return it if one exists,
1408// else return NULL.
1409//----------------------------------------------------------------------
1410const char*
1411DWARFDebugInfoEntry::GetName
1412(
1413    SymbolFileDWARF* dwarf2Data,
1414    const DWARFCompileUnit* cu
1415) const
1416{
1417    DWARFFormValue form_value;
1418    if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1419        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
1420    return NULL;
1421}
1422
1423
1424//----------------------------------------------------------------------
1425// GetMangledName
1426//
1427// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
1428// one exists, else return the value of the DW_AT_name attribute
1429//----------------------------------------------------------------------
1430const char*
1431DWARFDebugInfoEntry::GetMangledName
1432(
1433    SymbolFileDWARF* dwarf2Data,
1434    const DWARFCompileUnit* cu,
1435    bool substitute_name_allowed
1436) const
1437{
1438    const char* name = NULL;
1439    DWARFFormValue form_value;
1440
1441    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
1442        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1443
1444    if (substitute_name_allowed && name == NULL)
1445    {
1446        if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1447            name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1448    }
1449    return name;
1450}
1451
1452
1453//----------------------------------------------------------------------
1454// GetPubname
1455//
1456// Get value the name for a DIE as it should appear for a
1457// .debug_pubnames or .debug_pubtypes section.
1458//----------------------------------------------------------------------
1459const char*
1460DWARFDebugInfoEntry::GetPubname
1461(
1462    SymbolFileDWARF* dwarf2Data,
1463    const DWARFCompileUnit* cu
1464) const
1465{
1466    const char* name = NULL;
1467    DWARFFormValue form_value;
1468
1469    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
1470        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1471    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1472        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1473    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
1474    {
1475        // The specification DIE may be in another compile unit so we need
1476        // to get a die and its compile unit.
1477        DWARFCompileUnitSP cu_sp_ptr;
1478        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
1479        if (die)
1480            return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
1481    }
1482    return name;
1483}
1484
1485
1486//----------------------------------------------------------------------
1487// GetName
1488//
1489// Get value of the DW_AT_name attribute for a debug information entry
1490// that exists at offset "die_offset" and place that value into the
1491// supplied stream object. If the DIE is a NULL object "NULL" is placed
1492// into the stream, and if no DW_AT_name attribute exists for the DIE
1493// then nothing is printed.
1494//----------------------------------------------------------------------
1495bool
1496DWARFDebugInfoEntry::GetName
1497(
1498    SymbolFileDWARF* dwarf2Data,
1499    const DWARFCompileUnit* cu,
1500    const uint32_t die_offset,
1501    Stream &s
1502)
1503{
1504    DWARFDebugInfoEntry die;
1505    uint32_t offset = die_offset;
1506    if (die.Extract(dwarf2Data, cu, &offset))
1507    {
1508        if (die.IsNULL())
1509        {
1510            s.PutCString("NULL");
1511            return true;
1512        }
1513        else
1514        {
1515            DWARFFormValue form_value;
1516            if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1517            {
1518                const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1519                if (name)
1520                {
1521                    s.PutCString(name);
1522                    return true;
1523                }
1524            }
1525        }
1526    }
1527    return false;
1528}
1529
1530//----------------------------------------------------------------------
1531// AppendTypeName
1532//
1533// Follows the type name definition down through all needed tags to
1534// end up with a fully qualified type name and dump the results to
1535// the supplied stream. This is used to show the name of types given
1536// a type identifier.
1537//----------------------------------------------------------------------
1538bool
1539DWARFDebugInfoEntry::AppendTypeName
1540(
1541    SymbolFileDWARF* dwarf2Data,
1542    const DWARFCompileUnit* cu,
1543    const uint32_t die_offset,
1544    Stream &s
1545)
1546{
1547    DWARFDebugInfoEntry die;
1548    uint32_t offset = die_offset;
1549    if (die.Extract(dwarf2Data, cu, &offset))
1550    {
1551        if (die.IsNULL())
1552        {
1553            s.PutCString("NULL");
1554            return true;
1555        }
1556        else
1557        {
1558            const char* name = die.GetPubname(dwarf2Data, cu);
1559        //  if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1560        //      name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1561            if (name)
1562                s.PutCString(name);
1563            else
1564            {
1565                bool result = true;
1566                const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr(cu);
1567
1568                switch (abbrevDecl->Tag())
1569                {
1570                case DW_TAG_array_type:         break;  // print out a "[]" after printing the full type of the element below
1571                case DW_TAG_base_type:          s.PutCString("base ");         break;
1572                case DW_TAG_class_type:         s.PutCString("class ");            break;
1573                case DW_TAG_const_type:         s.PutCString("const ");            break;
1574                case DW_TAG_enumeration_type:   s.PutCString("enum ");         break;
1575                case DW_TAG_file_type:          s.PutCString("file ");         break;
1576                case DW_TAG_interface_type:     s.PutCString("interface ");        break;
1577                case DW_TAG_packed_type:        s.PutCString("packed ");       break;
1578                case DW_TAG_pointer_type:       break;  // print out a '*' after printing the full type below
1579                case DW_TAG_ptr_to_member_type: break;  // print out a '*' after printing the full type below
1580                case DW_TAG_reference_type:     break;  // print out a '&' after printing the full type below
1581                case DW_TAG_restrict_type:      s.PutCString("restrict ");     break;
1582                case DW_TAG_set_type:           s.PutCString("set ");          break;
1583                case DW_TAG_shared_type:        s.PutCString("shared ");       break;
1584                case DW_TAG_string_type:        s.PutCString("string ");       break;
1585                case DW_TAG_structure_type:     s.PutCString("struct ");       break;
1586                case DW_TAG_subrange_type:      s.PutCString("subrange ");     break;
1587                case DW_TAG_subroutine_type:    s.PutCString("function ");     break;
1588                case DW_TAG_thrown_type:        s.PutCString("thrown ");       break;
1589                case DW_TAG_union_type:         s.PutCString("union ");            break;
1590                case DW_TAG_unspecified_type:   s.PutCString("unspecified ");  break;
1591                case DW_TAG_volatile_type:      s.PutCString("volatile ");     break;
1592                default:
1593                    return false;
1594                }
1595
1596                // Follow the DW_AT_type if possible
1597                DWARFFormValue form_value;
1598                if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value))
1599                {
1600                    uint64_t next_die_offset = form_value.Reference(cu);
1601                    result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
1602                }
1603
1604                switch (abbrevDecl->Tag())
1605                {
1606                case DW_TAG_array_type:         s.PutCString("[]");    break;
1607                case DW_TAG_pointer_type:       s.PutChar('*');    break;
1608                case DW_TAG_ptr_to_member_type: s.PutChar('*');    break;
1609                case DW_TAG_reference_type:     s.PutChar('&');    break;
1610                default:
1611                    break;
1612                }
1613                return result;
1614            }
1615        }
1616    }
1617    return false;
1618}
1619
1620bool
1621DWARFDebugInfoEntry::Contains (const DWARFDebugInfoEntry *die) const
1622{
1623    if (die)
1624    {
1625        const dw_offset_t die_offset = die->GetOffset();
1626        if (die_offset > GetOffset())
1627        {
1628            const DWARFDebugInfoEntry *sibling = GetSibling();
1629            assert (sibling); // TODO: take this out
1630            if (sibling)
1631                return die_offset < sibling->GetOffset();
1632        }
1633    }
1634    return false;
1635}
1636
1637//----------------------------------------------------------------------
1638// BuildAddressRangeTable
1639//----------------------------------------------------------------------
1640void
1641DWARFDebugInfoEntry::BuildAddressRangeTable
1642(
1643    SymbolFileDWARF* dwarf2Data,
1644    const DWARFCompileUnit* cu,
1645    DWARFDebugAranges* debug_aranges
1646) const
1647{
1648    if (m_tag)
1649    {
1650        if (m_tag == DW_TAG_subprogram)
1651        {
1652            dw_addr_t hi_pc = DW_INVALID_ADDRESS;
1653            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1654            if (lo_pc != DW_INVALID_ADDRESS)
1655                hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1656            if (hi_pc != DW_INVALID_ADDRESS)
1657            {
1658            /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc);
1659                debug_aranges->AppendRange (cu->GetOffset(), lo_pc, hi_pc);
1660            }
1661        }
1662
1663
1664        const DWARFDebugInfoEntry* child = GetFirstChild();
1665        while (child)
1666        {
1667            child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges);
1668            child = child->GetSibling();
1669        }
1670    }
1671}
1672
1673//----------------------------------------------------------------------
1674// BuildFunctionAddressRangeTable
1675//
1676// This function is very similar to the BuildAddressRangeTable function
1677// except that the actual DIE offset for the function is placed in the
1678// table instead of the compile unit offset (which is the way the
1679// standard .debug_aranges section does it).
1680//----------------------------------------------------------------------
1681void
1682DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
1683(
1684    SymbolFileDWARF* dwarf2Data,
1685    const DWARFCompileUnit* cu,
1686    DWARFDebugAranges* debug_aranges
1687) const
1688{
1689    if (m_tag)
1690    {
1691        if (m_tag == DW_TAG_subprogram)
1692        {
1693            dw_addr_t hi_pc = DW_INVALID_ADDRESS;
1694            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1695            if (lo_pc != DW_INVALID_ADDRESS)
1696                hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1697            if (hi_pc != DW_INVALID_ADDRESS)
1698            {
1699            //  printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16llx - 0x%16.16llx)\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY
1700                debug_aranges->AppendRange (GetOffset(), lo_pc, hi_pc);
1701            }
1702        }
1703
1704        const DWARFDebugInfoEntry* child = GetFirstChild();
1705        while (child)
1706        {
1707            child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges);
1708            child = child->GetSibling();
1709        }
1710    }
1711}
1712
1713
1714//----------------------------------------------------------------------
1715// LookupAddress
1716//----------------------------------------------------------------------
1717bool
1718DWARFDebugInfoEntry::LookupAddress
1719(
1720    const dw_addr_t address,
1721    SymbolFileDWARF* dwarf2Data,
1722    const DWARFCompileUnit* cu,
1723    DWARFDebugInfoEntry** function_die,
1724    DWARFDebugInfoEntry** block_die
1725)
1726{
1727    bool found_address = false;
1728    if (m_tag)
1729    {
1730        bool check_children = false;
1731        bool match_addr_range = false;
1732    //  printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, DW_TAG_value_to_name(tag), address);
1733        switch (m_tag)
1734        {
1735        case DW_TAG_array_type                 : break;
1736        case DW_TAG_class_type                 : check_children = true; break;
1737        case DW_TAG_entry_point                : break;
1738        case DW_TAG_enumeration_type           : break;
1739        case DW_TAG_formal_parameter           : break;
1740        case DW_TAG_imported_declaration       : break;
1741        case DW_TAG_label                      : break;
1742        case DW_TAG_lexical_block              : check_children = true; match_addr_range = true; break;
1743        case DW_TAG_member                     : break;
1744        case DW_TAG_pointer_type               : break;
1745        case DW_TAG_reference_type             : break;
1746        case DW_TAG_compile_unit               : match_addr_range = true; break;
1747        case DW_TAG_string_type                : break;
1748        case DW_TAG_structure_type             : check_children = true; break;
1749        case DW_TAG_subroutine_type            : break;
1750        case DW_TAG_typedef                    : break;
1751        case DW_TAG_union_type                 : break;
1752        case DW_TAG_unspecified_parameters     : break;
1753        case DW_TAG_variant                    : break;
1754        case DW_TAG_common_block               : check_children = true; break;
1755        case DW_TAG_common_inclusion           : break;
1756        case DW_TAG_inheritance                : break;
1757        case DW_TAG_inlined_subroutine         : check_children = true; match_addr_range = true; break;
1758        case DW_TAG_module                     : match_addr_range = true; break;
1759        case DW_TAG_ptr_to_member_type         : break;
1760        case DW_TAG_set_type                   : break;
1761        case DW_TAG_subrange_type              : break;
1762        case DW_TAG_with_stmt                  : break;
1763        case DW_TAG_access_declaration         : break;
1764        case DW_TAG_base_type                  : break;
1765        case DW_TAG_catch_block                : match_addr_range = true; break;
1766        case DW_TAG_const_type                 : break;
1767        case DW_TAG_constant                   : break;
1768        case DW_TAG_enumerator                 : break;
1769        case DW_TAG_file_type                  : break;
1770        case DW_TAG_friend                     : break;
1771        case DW_TAG_namelist                   : break;
1772        case DW_TAG_namelist_item              : break;
1773        case DW_TAG_packed_type                : break;
1774        case DW_TAG_subprogram                 : match_addr_range = true; break;
1775        case DW_TAG_template_type_parameter    : break;
1776        case DW_TAG_template_value_parameter   : break;
1777        case DW_TAG_thrown_type                : break;
1778        case DW_TAG_try_block                  : match_addr_range = true; break;
1779        case DW_TAG_variant_part               : break;
1780        case DW_TAG_variable                   : break;
1781        case DW_TAG_volatile_type              : break;
1782        case DW_TAG_dwarf_procedure            : break;
1783        case DW_TAG_restrict_type              : break;
1784        case DW_TAG_interface_type             : break;
1785        case DW_TAG_namespace                  : check_children = true; break;
1786        case DW_TAG_imported_module            : break;
1787        case DW_TAG_unspecified_type           : break;
1788        case DW_TAG_partial_unit               : break;
1789        case DW_TAG_imported_unit              : break;
1790        case DW_TAG_shared_type                : break;
1791        default: break;
1792        }
1793
1794        if (match_addr_range)
1795        {
1796            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1797            if (lo_pc != DW_INVALID_ADDRESS)
1798            {
1799                dw_addr_t hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1800                if (hi_pc != DW_INVALID_ADDRESS)
1801                {
1802                    //  printf("\n0x%8.8x: %30s: address = 0x%8.8x  [0x%8.8x - 0x%8.8x) ", m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
1803                    if ((lo_pc <= address) && (address < hi_pc))
1804                    {
1805                        found_address = true;
1806                    //  puts("***MATCH***");
1807                        switch (m_tag)
1808                        {
1809                        case DW_TAG_compile_unit:       // File
1810                            check_children = ((function_die != NULL) || (block_die != NULL));
1811                            break;
1812
1813                        case DW_TAG_subprogram:         // Function
1814                            if (function_die)
1815                                *function_die = this;
1816                            check_children = (block_die != NULL);
1817                            break;
1818
1819                        case DW_TAG_inlined_subroutine: // Inlined Function
1820                        case DW_TAG_lexical_block:      // Block { } in code
1821                            if (block_die)
1822                            {
1823                                *block_die = this;
1824                                check_children = true;
1825                            }
1826                            break;
1827
1828                        default:
1829                            check_children = true;
1830                            break;
1831                        }
1832                    }
1833                }
1834                else
1835                {   // compile units may not have a valid high/low pc when there
1836                    // are address gaps in subroutines so we must always search
1837                    // if there is no valid high and low PC
1838                    check_children = (m_tag == DW_TAG_compile_unit) && ((function_die != NULL) || (block_die != NULL));
1839                }
1840            }
1841            else
1842            {
1843                dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
1844                if (debug_ranges_offset != DW_INVALID_OFFSET)
1845                {
1846                    DWARFDebugRanges::RangeList ranges;
1847                    DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
1848                    debug_ranges->FindRanges(debug_ranges_offset, ranges);
1849                    // All DW_AT_ranges are relative to the base address of the
1850                    // compile unit. We add the compile unit base address to make
1851                    // sure all the addresses are properly fixed up.
1852                    ranges.Slide (cu->GetBaseAddress());
1853                    if (ranges.FindEntryThatContains(address))
1854                    {
1855                        found_address = true;
1856                    //  puts("***MATCH***");
1857                        switch (m_tag)
1858                        {
1859                        case DW_TAG_compile_unit:       // File
1860                            check_children = ((function_die != NULL) || (block_die != NULL));
1861                            break;
1862
1863                        case DW_TAG_subprogram:         // Function
1864                            if (function_die)
1865                                *function_die = this;
1866                            check_children = (block_die != NULL);
1867                            break;
1868
1869                        case DW_TAG_inlined_subroutine: // Inlined Function
1870                        case DW_TAG_lexical_block:      // Block { } in code
1871                            if (block_die)
1872                            {
1873                                *block_die = this;
1874                                check_children = true;
1875                            }
1876                            break;
1877
1878                        default:
1879                            check_children = true;
1880                            break;
1881                        }
1882                    }
1883                    else
1884                    {
1885                        check_children = false;
1886                    }
1887                }
1888            }
1889        }
1890
1891
1892        if (check_children)
1893        {
1894        //  printf("checking children\n");
1895            DWARFDebugInfoEntry* child = GetFirstChild();
1896            while (child)
1897            {
1898                if (child->LookupAddress(address, dwarf2Data, cu, function_die, block_die))
1899                    return true;
1900                child = child->GetSibling();
1901            }
1902        }
1903    }
1904    return found_address;
1905}
1906
1907const DWARFAbbreviationDeclaration*
1908DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (const DWARFCompileUnit *cu) const
1909{
1910    if (m_abbr_idx)
1911        return cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx);
1912    return NULL;
1913}
1914
1915
1916bool
1917DWARFDebugInfoEntry::OffsetLessThan (const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b)
1918{
1919    return a.GetOffset() < b.GetOffset();
1920}
1921
1922