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