blob: 19eef06d3d166c4011b7521fea52741928efc56f [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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 m_infos.reserve(20);
41}
42
43DWARFDebugInfoEntry::Attributes::~Attributes()
44{
45}
46
47
48uint32_t
49DWARFDebugInfoEntry::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
62void
63DWARFDebugInfoEntry::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
69bool
70DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
71{
72 return FindAttributeIndex(attr) != UINT_MAX;
73}
74
75bool
76DWARFDebugInfoEntry::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
87bool
88DWARFDebugInfoEntry::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
95uint64_t
96DWARFDebugInfoEntry::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//----------------------------------------------------------------------
112bool
113DWARFDebugInfoEntry::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 {
165die_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//----------------------------------------------------------------------
275bool
276DWARFDebugInfoEntry::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//----------------------------------------------------------------------
481void
482DWARFDebugInfoEntry::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//----------------------------------------------------------------------
505int
506DWARFDebugInfoEntry::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
527int
528DWARFDebugInfoEntry::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//----------------------------------------------------------------------
774bool
775DWARFDebugInfoEntry::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//----------------------------------------------------------------------
958void
959DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1029void
1030DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1191size_t
1192DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1260dw_offset_t
1261DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1309const char*
1310DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1328uint64_t
1329DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1348int64_t
1349DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1369uint64_t
1370DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1390dw_offset_t
1391DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1440const char*
1441DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1460const char*
1461DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1489const char*
1490DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1525bool
1526DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1568bool
1569DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1653void
1654DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1695void
1696DWARFDebugInfoEntry::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//----------------------------------------------------------------------
1732bool
1733DWARFDebugInfoEntry::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
1924bool
1925DWARFDebugInfoEntry::OffsetLessThan (const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b)
1926{
1927 return a.GetOffset() < b.GetOffset();
1928}
1929