blob: 50a7e9ba5edfb91fb027808794c22f15f1081fc6 [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 }
Greg Clayton178710c2010-09-14 02:20:48 +000059 return UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +000060}
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{
Greg Clayton178710c2010-09-14 02:20:48 +000072 return FindAttributeIndex(attr) != UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +000073}
74
75bool
76DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
77{
78 uint32_t attr_index = FindAttributeIndex(attr);
Greg Clayton178710c2010-09-14 02:20:48 +000079 if (attr_index != UINT32_MAX)
Chris Lattner24943d22010-06-08 16:52:24 +000080 {
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);
Greg Clayton178710c2010-09-14 02:20:48 +0000587 uint32_t a_name_index = UINT32_MAX;
588 uint32_t b_name_index = UINT32_MAX;
589 if (is_decl_index != UINT32_MAX)
Chris Lattner24943d22010-06-08 16:52:24 +0000590 {
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);
Greg Clayton178710c2010-09-14 02:20:48 +0000600 if (is_decl_index != UINT32_MAX && a_attr_count == 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000601 {
602 a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
603 b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
604 }
605 }
Greg Clayton178710c2010-09-14 02:20:48 +0000606 if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX)
Chris Lattner24943d22010-06-08 16:52:24 +0000607 {
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;
Greg Clayton178710c2010-09-14 02:20:48 +0000797 bool set_frame_base_loclist_addr = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000798 if (m_abbrevDecl)
799 {
800 const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
801 uint32_t offset = m_offset;
802
803 if (!debug_info_data.ValidOffset(offset))
804 return false;
805
806 // Skip the abbreviation code
807 debug_info_data.Skip_LEB128(&offset);
808
809 const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
810 uint32_t i;
811 dw_attr_t attr;
812 dw_form_t form;
813 for (i=0; i<numAttributes; ++i)
814 {
815 m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
816 DWARFFormValue form_value(form);
817 if (form_value.ExtractValue(debug_info_data, &offset, cu))
818 {
819 switch (attr)
820 {
821 case DW_AT_low_pc:
822 case DW_AT_entry_pc:
823 lo_pc = form_value.Unsigned();
824 break;
825
826 case DW_AT_high_pc:
827 hi_pc = form_value.Unsigned();
828 break;
829
830 case DW_AT_ranges:
831 {
832 const DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
833 debug_ranges->FindRanges(form_value.Unsigned(), ranges);
834 // All DW_AT_ranges are relative to the base address of the
835 // compile unit. We add the compile unit base address to make
836 // sure all the addresses are properly fixed up.
837 ranges.AddOffset(cu->GetBaseAddress());
838 }
839 break;
840
841 case DW_AT_name:
842 if (name == NULL)
843 name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
844 break;
845
846 case DW_AT_MIPS_linkage_name:
847 if (mangled == NULL)
848 mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
849 break;
850
851 case DW_AT_abstract_origin:
852 die_offsets.push_back(form_value.Reference(cu));
853 break;
854
855 case DW_AT_specification:
856 die_offsets.push_back(form_value.Reference(cu));
857 break;
858
859 case DW_AT_decl_file:
860 if (decl_file == 0)
861 decl_file = form_value.Unsigned();
862 break;
863
864 case DW_AT_decl_line:
865 if (decl_line == 0)
866 decl_line = form_value.Unsigned();
867 break;
868
869 case DW_AT_decl_column:
870 if (decl_column == 0)
871 decl_column = form_value.Unsigned();
872 break;
873
874 case DW_AT_call_file:
875 if (call_file == 0)
876 call_file = form_value.Unsigned();
877 break;
878
879 case DW_AT_call_line:
880 if (call_line == 0)
881 call_line = form_value.Unsigned();
882 break;
883
884 case DW_AT_call_column:
885 if (call_column == 0)
886 call_column = form_value.Unsigned();
887 break;
888
889 case DW_AT_frame_base:
890 if (frame_base)
891 {
892 if (form_value.BlockData())
893 {
894 uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
895 uint32_t block_length = form_value.Unsigned();
Greg Clayton178710c2010-09-14 02:20:48 +0000896 frame_base->SetOpcodeData(debug_info_data, block_offset, block_length);
Chris Lattner24943d22010-06-08 16:52:24 +0000897 }
898 else
899 {
Greg Clayton178710c2010-09-14 02:20:48 +0000900 const DataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
Chris Lattner24943d22010-06-08 16:52:24 +0000901 const dw_offset_t debug_loc_offset = form_value.Unsigned();
902
903 size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
904 if (loc_list_length > 0)
905 {
Greg Clayton178710c2010-09-14 02:20:48 +0000906 frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
907 if (lo_pc != DW_INVALID_ADDRESS)
908 {
909 assert (lo_pc >= cu->GetBaseAddress());
910 frame_base->SetLocationListSlide(lo_pc - cu->GetBaseAddress());
911 }
912 else
913 {
914 set_frame_base_loclist_addr = true;
915 }
Chris Lattner24943d22010-06-08 16:52:24 +0000916 }
917 }
918 }
919 break;
920
921 default:
922 break;
923 }
924 }
925 }
926 }
927
928 size_t numRanges = ranges.Size();
929
930 if (numRanges == 0)
931 {
932 if (lo_pc != DW_INVALID_ADDRESS)
933 {
934 if (hi_pc != DW_INVALID_ADDRESS)
935 ranges.AddRange(lo_pc, hi_pc);
936 else
937 ranges.AddRange(lo_pc, lo_pc);
938 }
939 }
Greg Clayton178710c2010-09-14 02:20:48 +0000940
941 if (set_frame_base_loclist_addr)
942 {
943 assert (ranges.LowestAddress(0) >= cu->GetBaseAddress());
944 frame_base->SetLocationListSlide(ranges.LowestAddress(0) - cu->GetBaseAddress());
945 }
Chris Lattner24943d22010-06-08 16:52:24 +0000946
947 if (ranges.Size() == 0 || (name == NULL) || (mangled == NULL))
948 {
949 std::vector<dw_offset_t>::const_iterator pos;
950 std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
951 for (pos = die_offsets.begin(); pos != end; ++pos)
952 {
953 DWARFCompileUnitSP cu_sp_ptr;
954 const DWARFDebugInfoEntry* die = NULL;
955 dw_offset_t die_offset = *pos;
956 if (die_offset != DW_INVALID_OFFSET)
957 {
958 die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
959 if (die)
960 die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
961 }
962 }
963 }
964 return ranges.Size() > 0;
965}
966
967//----------------------------------------------------------------------
968// Dump
969//
970// Dumps a debug information entry and all of it's attributes to the
971// specified stream.
972//----------------------------------------------------------------------
973void
974DWARFDebugInfoEntry::Dump
975(
976 SymbolFileDWARF* dwarf2Data,
977 const DWARFCompileUnit* cu,
978 Stream *s,
979 uint32_t recurse_depth
980) const
981{
982 const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
983 uint32_t offset = m_offset;
984 bool english = s->GetFlags().IsSet (DWARFDebugInfo::eDumpFlag_EnglishyNames);
985
986 if (debug_info_data.ValidOffset(offset))
987 {
988 dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset);
989
990 s->Printf("\n0x%8.8x: ", m_offset);
991 s->Indent();
992 if (abbrCode)
993 {
994 if (m_abbrevDecl)
995 {
996 if (english)
997 s->PutCString(DW_TAG_value_to_englishy_name(m_abbrevDecl->Tag()));
998 else
999 s->PutCString(DW_TAG_value_to_name(m_abbrevDecl->Tag()));
1000 s->Printf( " [%u] %c\n", abbrCode, m_abbrevDecl->HasChildren() ? '*':' ');
1001
1002 // Dump all data in the .debug_info for the attributes
1003 const uint32_t numAttributes = m_abbrevDecl->NumAttributes();
1004 uint32_t i;
1005 dw_attr_t attr;
1006 dw_form_t form;
1007 for (i=0; i<numAttributes; ++i)
1008 {
1009 m_abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
1010
1011 DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, form);
1012 }
1013
1014 const DWARFDebugInfoEntry* child = GetFirstChild();
1015 if (recurse_depth > 0 && child)
1016 {
1017 s->IndentMore();
1018
1019 while (child)
1020 {
1021 child->Dump(dwarf2Data, cu, s, recurse_depth-1);
1022 child = child->GetSibling();
1023 }
1024 s->IndentLess();
1025 }
1026 }
1027 else
1028 s->Printf( "Abbreviation code note found in 'debug_abbrev' class for code: %u\n", abbrCode);
1029 }
1030 else
1031 {
1032 s->Printf( "NULL\n");
1033 }
1034 }
1035}
1036
1037//----------------------------------------------------------------------
1038// DumpAttribute
1039//
1040// Dumps a debug information entry attribute along with it's form. Any
1041// special display of attributes is done (disassemble location lists,
1042// show enumeration values for attributes, etc).
1043//----------------------------------------------------------------------
1044void
1045DWARFDebugInfoEntry::DumpAttribute
1046(
1047 SymbolFileDWARF* dwarf2Data,
1048 const DWARFCompileUnit* cu,
1049 const DataExtractor& debug_info_data,
1050 uint32_t* offset_ptr,
1051 Stream *s,
1052 dw_attr_t attr,
1053 dw_form_t form
1054)
1055{
1056 bool verbose = s->GetVerbose();
1057 bool show_form = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_ShowForm);
1058 bool english = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_EnglishyNames);
1059 const DataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
1060 if (verbose)
1061 s->Offset(*offset_ptr);
1062 else
1063 s->Printf( " ");
1064 s->Indent();
1065
1066 if (english)
1067 s->PutCString(DW_AT_value_to_englishy_name(attr));
1068 else
1069 s->PutCString(DW_AT_value_to_name(attr));
1070
1071 if (show_form)
1072 {
1073 s->Printf( "[%s", english ? DW_FORM_value_to_englishy_name(form) : DW_FORM_value_to_name(form));
1074 }
1075
1076 DWARFFormValue form_value(form);
1077
1078 if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu))
1079 return;
1080
1081 if (show_form)
1082 {
1083 if (form == DW_FORM_indirect)
1084 {
1085 s->Printf( " [%s]", english ? DW_FORM_value_to_englishy_name(form_value.Form()) : DW_FORM_value_to_name(form_value.Form()));
1086 }
1087
1088 s->PutCString("] ");
1089 }
1090
1091 s->PutCString("( ");
1092
1093 // Always dump form value if verbose is enabled
1094 if (verbose)
1095 {
1096 form_value.Dump(s, debug_str_data, cu);
1097 }
1098
1099
1100 // Check to see if we have any special attribute formatters
1101 switch (attr)
1102 {
1103 case DW_AT_stmt_list:
1104 if ( verbose ) s->PutCString(" ( ");
1105 s->Printf( "0x%8.8x", form_value.Unsigned());
1106 if ( verbose ) s->PutCString(" )");
1107 break;
1108
1109 case DW_AT_language:
1110 if ( verbose ) s->PutCString(" ( ");
1111 s->PutCString(DW_LANG_value_to_name(form_value.Unsigned()));
1112 if ( verbose ) s->PutCString(" )");
1113 break;
1114
1115 case DW_AT_encoding:
1116 if ( verbose ) s->PutCString(" ( ");
1117 s->PutCString(DW_ATE_value_to_name(form_value.Unsigned()));
1118 if ( verbose ) s->PutCString(" )");
1119 break;
1120
1121 case DW_AT_frame_base:
1122 case DW_AT_location:
1123 case DW_AT_data_member_location:
1124 {
1125 const uint8_t* blockData = form_value.BlockData();
1126 if (blockData)
1127 {
1128 if (!verbose)
1129 form_value.Dump(s, debug_str_data, cu);
1130
1131 // Location description is inlined in data in the form value
1132 DataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
1133 if ( verbose ) s->PutCString(" ( ");
1134 print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
1135 if ( verbose ) s->PutCString(" )");
1136 }
1137 else
1138 {
1139 // We have a location list offset as the value that is
1140 // the offset into the .debug_loc section that describes
1141 // the value over it's lifetime
1142 uint64_t debug_loc_offset = form_value.Unsigned();
1143 if (dwarf2Data)
1144 {
1145 if ( !verbose )
1146 form_value.Dump(s, debug_str_data, cu);
1147 DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
1148 }
1149 else
1150 {
1151 if ( !verbose )
1152 form_value.Dump(s, NULL, cu);
1153 }
1154 }
1155 }
1156 break;
1157
1158 case DW_AT_abstract_origin:
1159 case DW_AT_specification:
1160 {
1161 uint64_t abstract_die_offset = form_value.Reference(cu);
1162 form_value.Dump(s, debug_str_data, cu);
1163 // *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
1164 if ( verbose ) s->PutCString(" ( ");
1165 GetName(dwarf2Data, cu, abstract_die_offset, s);
1166 if ( verbose ) s->PutCString(" )");
1167 }
1168 break;
1169
1170 case DW_AT_type:
1171 {
1172 uint64_t type_die_offset = form_value.Reference(cu);
1173 if (!verbose)
1174 form_value.Dump(s, debug_str_data, cu);
1175 s->PutCString(" ( ");
1176 AppendTypeName(dwarf2Data, cu, type_die_offset, s);
1177 s->PutCString(" )");
1178 }
1179 break;
1180
1181 case DW_AT_ranges:
1182 {
1183 if ( !verbose )
1184 form_value.Dump(s, debug_str_data, cu);
1185 uint32_t ranges_offset = form_value.Unsigned();
1186 dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
1187 DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), &ranges_offset, base_addr);
1188 }
1189 break;
1190
1191 default:
1192 if ( !verbose )
1193 form_value.Dump(s, debug_str_data, cu);
1194 break;
1195 }
1196
1197 s->PutCString(" )\n");
1198}
1199
1200//----------------------------------------------------------------------
1201// Get all attribute values for a given DIE, including following any
1202// specification or abstract origin attributes and including those in
1203// the results. Any duplicate attributes will have the first instance
1204// take precedence (this can happen for declaration attributes).
1205//----------------------------------------------------------------------
1206size_t
1207DWARFDebugInfoEntry::GetAttributes
1208(
1209 SymbolFileDWARF* dwarf2Data,
1210 const DWARFCompileUnit* cu,
1211 DWARFDebugInfoEntry::Attributes& attributes
1212) const
1213{
1214 if (m_abbrevDecl)
1215 {
1216 uint32_t offset = GetOffset();
1217 const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
1218
1219 // Skip the abbreviation code so we are at the data for the attributes
1220 debug_info_data.Skip_LEB128(&offset);
1221
1222 const uint32_t num_attributes = m_abbrevDecl->NumAttributes();
1223 uint32_t i;
1224 dw_attr_t attr;
1225 dw_form_t form;
1226 DWARFFormValue form_value;
1227 for (i=0; i<num_attributes; ++i)
1228 {
1229 m_abbrevDecl->GetAttrAndFormByIndexUnchecked (i, attr, form);
1230 attributes.Append(cu, offset, attr, form);
1231 if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))
1232 {
1233 form_value.SetForm(form);
1234 if (form_value.ExtractValue(debug_info_data, &offset, cu))
1235 {
1236 const DWARFDebugInfoEntry* die = NULL;
1237 dw_offset_t die_offset = form_value.Reference(cu);
1238 if (cu->ContainsDIEOffset(die_offset))
1239 {
1240 die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
1241 if (die)
1242 die->GetAttributes(dwarf2Data, cu, attributes);
1243 }
1244 else
1245 {
1246 DWARFCompileUnitSP cu_sp_ptr;
1247 die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
1248 if (die)
1249 die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), attributes);
1250 }
1251 }
1252 }
1253 else
1254 {
1255 assert(DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu));
1256 }
1257 }
1258 }
1259 else
1260 {
1261 attributes.Clear();
1262 }
1263 return attributes.Size();
1264
1265}
1266
1267//----------------------------------------------------------------------
1268// GetAttributeValue
1269//
1270// Get the value of an attribute and return the .debug_info offset of the
1271// attribute if it was properly extracted into form_value, or zero
1272// if we fail since an offset of zero is invalid for an attribute (it
1273// would be a compile unit header).
1274//----------------------------------------------------------------------
1275dw_offset_t
1276DWARFDebugInfoEntry::GetAttributeValue
1277(
1278 SymbolFileDWARF* dwarf2Data,
1279 const DWARFCompileUnit* cu,
1280 const dw_attr_t attr,
1281 DWARFFormValue& form_value,
1282 dw_offset_t* end_attr_offset_ptr
1283) const
1284{
1285 if (m_abbrevDecl)
1286 {
1287 uint32_t attr_idx = m_abbrevDecl->FindAttributeIndex(attr);
1288
1289 if (attr_idx != DW_INVALID_INDEX)
1290 {
1291 uint32_t offset = GetOffset();
1292
1293 const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
1294
1295 // Skip the abbreviation code so we are at the data for the attributes
1296 debug_info_data.Skip_LEB128(&offset);
1297
1298 uint32_t idx=0;
1299 while (idx<attr_idx)
1300 DWARFFormValue::SkipValue(m_abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu);
1301
1302 const dw_offset_t attr_offset = offset;
1303 form_value.SetForm(m_abbrevDecl->GetFormByIndex(idx));
1304 if (form_value.ExtractValue(debug_info_data, &offset, cu))
1305 {
1306 if (end_attr_offset_ptr)
1307 *end_attr_offset_ptr = offset;
1308 return attr_offset;
1309 }
1310 }
1311 }
1312
1313 return 0;
1314}
1315
1316//----------------------------------------------------------------------
1317// GetAttributeValueAsString
1318//
1319// Get the value of an attribute as a string return it. The resulting
1320// pointer to the string data exists within the supplied SymbolFileDWARF
1321// and will only be available as long as the SymbolFileDWARF is still around
1322// and it's content doesn't change.
1323//----------------------------------------------------------------------
1324const char*
1325DWARFDebugInfoEntry::GetAttributeValueAsString
1326(
1327 SymbolFileDWARF* dwarf2Data,
1328 const DWARFCompileUnit* cu,
1329 const dw_attr_t attr,
1330 const char* fail_value) const
1331{
1332 DWARFFormValue form_value;
1333 if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1334 return form_value.AsCString(&dwarf2Data->get_debug_str_data());
1335 return fail_value;
1336}
1337
1338//----------------------------------------------------------------------
1339// GetAttributeValueAsUnsigned
1340//
1341// Get the value of an attribute as unsigned and return it.
1342//----------------------------------------------------------------------
1343uint64_t
1344DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
1345(
1346 SymbolFileDWARF* dwarf2Data,
1347 const DWARFCompileUnit* cu,
1348 const dw_attr_t attr,
1349 uint64_t fail_value
1350) const
1351{
1352 DWARFFormValue form_value;
1353 if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1354 return form_value.Unsigned();
1355 return fail_value;
1356}
1357
1358//----------------------------------------------------------------------
1359// GetAttributeValueAsSigned
1360//
1361// Get the value of an attribute a signed value and return it.
1362//----------------------------------------------------------------------
1363int64_t
1364DWARFDebugInfoEntry::GetAttributeValueAsSigned
1365(
1366 SymbolFileDWARF* dwarf2Data,
1367 const DWARFCompileUnit* cu,
1368 const dw_attr_t attr,
1369 int64_t fail_value
1370) const
1371{
1372 DWARFFormValue form_value;
1373 if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1374 return form_value.Signed();
1375 return fail_value;
1376}
1377
1378//----------------------------------------------------------------------
1379// GetAttributeValueAsReference
1380//
1381// Get the value of an attribute as reference and fix up and compile
1382// unit relative offsets as needed.
1383//----------------------------------------------------------------------
1384uint64_t
1385DWARFDebugInfoEntry::GetAttributeValueAsReference
1386(
1387 SymbolFileDWARF* dwarf2Data,
1388 const DWARFCompileUnit* cu,
1389 const dw_attr_t attr,
1390 uint64_t fail_value
1391) const
1392{
1393 DWARFFormValue form_value;
1394 if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
1395 return form_value.Reference(cu);
1396 return fail_value;
1397}
1398
1399//----------------------------------------------------------------------
1400// GetAttributeValueAsLocation
1401//
1402// Get the value of an attribute as reference and fix up and compile
1403// unit relative offsets as needed.
1404//----------------------------------------------------------------------
1405dw_offset_t
1406DWARFDebugInfoEntry::GetAttributeValueAsLocation
1407(
1408 SymbolFileDWARF* dwarf2Data,
1409 const DWARFCompileUnit* cu,
1410 const dw_attr_t attr,
1411 DataExtractor& location_data,
1412 uint32_t &block_size
1413) const
1414{
1415 block_size = 0;
1416 DWARFFormValue form_value;
1417
1418 // Empty out data in case we don't find anything
1419 location_data.Clear();
1420 dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
1421 const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
1422 if (attr_offset)
1423 {
1424 const uint8_t* blockData = form_value.BlockData();
1425 if (blockData)
1426 {
1427 // We have an inlined location list in the .debug_info section
1428 const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
1429 dw_offset_t block_offset = blockData - debug_info.GetDataStart();
1430 block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
1431 location_data.SetData(debug_info, block_offset, block_size);
1432 }
1433 else
1434 {
1435 // We have a location list offset as the value that is
1436 // the offset into the .debug_loc section that describes
1437 // the value over it's lifetime
1438 dw_offset_t debug_loc_offset = form_value.Unsigned();
1439 if (dwarf2Data)
1440 {
1441 assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
1442 return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
1443 }
1444 }
1445 }
1446 return attr_offset;
1447}
1448
1449//----------------------------------------------------------------------
1450// GetName
1451//
1452// Get value of the DW_AT_name attribute and return it if one exists,
1453// else return NULL.
1454//----------------------------------------------------------------------
1455const char*
1456DWARFDebugInfoEntry::GetName
1457(
1458 SymbolFileDWARF* dwarf2Data,
1459 const DWARFCompileUnit* cu
1460) const
1461{
1462 DWARFFormValue form_value;
1463 if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1464 return form_value.AsCString(&dwarf2Data->get_debug_str_data());
1465 return NULL;
1466}
1467
1468
1469//----------------------------------------------------------------------
1470// GetMangledName
1471//
1472// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
1473// one exists, else return the value of the DW_AT_name attribute
1474//----------------------------------------------------------------------
1475const char*
1476DWARFDebugInfoEntry::GetMangledName
1477(
1478 SymbolFileDWARF* dwarf2Data,
1479 const DWARFCompileUnit* cu,
1480 bool substitute_name_allowed
1481) const
1482{
1483 const char* name = NULL;
1484 DWARFFormValue form_value;
1485
1486 if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
1487 name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1488
1489 if (substitute_name_allowed && name == NULL)
1490 {
1491 if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1492 name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1493 }
1494 return name;
1495}
1496
1497
1498//----------------------------------------------------------------------
1499// GetPubname
1500//
1501// Get value the name for a DIE as it should appear for a
1502// .debug_pubnames or .debug_pubtypes section.
1503//----------------------------------------------------------------------
1504const char*
1505DWARFDebugInfoEntry::GetPubname
1506(
1507 SymbolFileDWARF* dwarf2Data,
1508 const DWARFCompileUnit* cu
1509) const
1510{
1511 const char* name = NULL;
1512 DWARFFormValue form_value;
1513
1514 if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
1515 name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1516 else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1517 name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1518 else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
1519 {
1520 // The specification DIE may be in another compile unit so we need
1521 // to get a die and its compile unit.
1522 DWARFCompileUnitSP cu_sp_ptr;
1523 const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
1524 if (die)
1525 return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
1526 }
1527 return name;
1528}
1529
1530
1531//----------------------------------------------------------------------
1532// GetName
1533//
1534// Get value of the DW_AT_name attribute for a debug information entry
1535// that exists at offset "die_offset" and place that value into the
1536// supplied stream object. If the DIE is a NULL object "NULL" is placed
1537// into the stream, and if no DW_AT_name attribute exists for the DIE
1538// then nothing is printed.
1539//----------------------------------------------------------------------
1540bool
1541DWARFDebugInfoEntry::GetName
1542(
1543 SymbolFileDWARF* dwarf2Data,
1544 const DWARFCompileUnit* cu,
1545 const uint32_t die_offset,
1546 Stream *s
1547)
1548{
1549 DWARFDebugInfoEntry die;
1550 uint32_t offset = die_offset;
1551 if (die.Extract(dwarf2Data, cu, &offset))
1552 {
1553 if (die.IsNULL())
1554 {
1555 s->PutCString("NULL");
1556 return true;
1557 }
1558 else
1559 {
1560 DWARFFormValue form_value;
1561 if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1562 {
1563 const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1564 if (name)
1565 {
1566 s->PutCString(name);
1567 return true;
1568 }
1569 }
1570 }
1571 }
1572 return false;
1573}
1574
1575//----------------------------------------------------------------------
1576// AppendTypeName
1577//
1578// Follows the type name definition down through all needed tags to
1579// end up with a fully qualified type name and dump the results to
1580// the supplied stream. This is used to show the name of types given
1581// a type identifier.
1582//----------------------------------------------------------------------
1583bool
1584DWARFDebugInfoEntry::AppendTypeName
1585(
1586 SymbolFileDWARF* dwarf2Data,
1587 const DWARFCompileUnit* cu,
1588 const uint32_t die_offset,
1589 Stream *s
1590)
1591{
1592 DWARFDebugInfoEntry die;
1593 uint32_t offset = die_offset;
1594 if (die.Extract(dwarf2Data, cu, &offset))
1595 {
1596 if (die.IsNULL())
1597 {
1598 s->PutCString("NULL");
1599 return true;
1600 }
1601 else
1602 {
1603 const char* name = die.GetPubname(dwarf2Data, cu);
1604 // if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
1605 // name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
1606 if (name)
1607 s->PutCString(name);
1608 else
1609 {
1610 bool result = true;
1611 const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr();
1612
1613 switch (abbrevDecl->Tag())
1614 {
1615 case DW_TAG_array_type: break; // print out a "[]" after printing the full type of the element below
1616 case DW_TAG_base_type: s->PutCString("base "); break;
1617 case DW_TAG_class_type: s->PutCString("class "); break;
1618 case DW_TAG_const_type: s->PutCString("const "); break;
1619 case DW_TAG_enumeration_type: s->PutCString("enum "); break;
1620 case DW_TAG_file_type: s->PutCString("file "); break;
1621 case DW_TAG_interface_type: s->PutCString("interface "); break;
1622 case DW_TAG_packed_type: s->PutCString("packed "); break;
1623 case DW_TAG_pointer_type: break; // print out a '*' after printing the full type below
1624 case DW_TAG_ptr_to_member_type: break; // print out a '*' after printing the full type below
1625 case DW_TAG_reference_type: break; // print out a '&' after printing the full type below
1626 case DW_TAG_restrict_type: s->PutCString("restrict "); break;
1627 case DW_TAG_set_type: s->PutCString("set "); break;
1628 case DW_TAG_shared_type: s->PutCString("shared "); break;
1629 case DW_TAG_string_type: s->PutCString("string "); break;
1630 case DW_TAG_structure_type: s->PutCString("struct "); break;
1631 case DW_TAG_subrange_type: s->PutCString("subrange "); break;
1632 case DW_TAG_subroutine_type: s->PutCString("function "); break;
1633 case DW_TAG_thrown_type: s->PutCString("thrown "); break;
1634 case DW_TAG_union_type: s->PutCString("union "); break;
1635 case DW_TAG_unspecified_type: s->PutCString("unspecified "); break;
1636 case DW_TAG_volatile_type: s->PutCString("volatile "); break;
1637 default:
1638 return false;
1639 }
1640
1641 // Follow the DW_AT_type if possible
1642 DWARFFormValue form_value;
1643 if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value))
1644 {
1645 uint64_t next_die_offset = form_value.Reference(cu);
1646 result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
1647 }
1648
1649 switch (abbrevDecl->Tag())
1650 {
1651 case DW_TAG_array_type: s->PutCString("[]"); break;
1652 case DW_TAG_pointer_type: s->PutChar('*'); break;
1653 case DW_TAG_ptr_to_member_type: s->PutChar('*'); break;
1654 case DW_TAG_reference_type: s->PutChar('&'); break;
1655 default:
1656 break;
1657 }
1658 return result;
1659 }
1660 }
1661 }
1662 return false;
1663}
1664
1665//----------------------------------------------------------------------
1666// BuildAddressRangeTable
1667//----------------------------------------------------------------------
1668void
1669DWARFDebugInfoEntry::BuildAddressRangeTable
1670(
1671 SymbolFileDWARF* dwarf2Data,
1672 const DWARFCompileUnit* cu,
1673 DWARFDebugAranges* debug_aranges
1674) const
1675{
1676 if (m_abbrevDecl)
1677 {
1678 dw_tag_t tag = m_abbrevDecl->Tag();
1679 if (tag == DW_TAG_subprogram)
1680 {
1681 dw_addr_t hi_pc = DW_INVALID_ADDRESS;
1682 dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1683 if (lo_pc != DW_INVALID_ADDRESS)
1684 hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1685 if (hi_pc != DW_INVALID_ADDRESS)
1686 {
1687 /// 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);
1688 debug_aranges->InsertRange(cu->GetOffset(), lo_pc, hi_pc);
1689 }
1690 }
1691
1692
1693 const DWARFDebugInfoEntry* child = GetFirstChild();
1694 while (child)
1695 {
1696 child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges);
1697 child = child->GetSibling();
1698 }
1699 }
1700}
1701
1702//----------------------------------------------------------------------
1703// BuildFunctionAddressRangeTable
1704//
1705// This function is very similar to the BuildAddressRangeTable function
1706// except that the actual DIE offset for the function is placed in the
1707// table instead of the compile unit offset (which is the way the
1708// standard .debug_aranges section does it).
1709//----------------------------------------------------------------------
1710void
1711DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
1712(
1713 SymbolFileDWARF* dwarf2Data,
1714 const DWARFCompileUnit* cu,
1715 DWARFDebugAranges* debug_aranges
1716) const
1717{
1718 if (m_abbrevDecl)
1719 {
1720 dw_tag_t tag = m_abbrevDecl->Tag();
1721 if (tag == DW_TAG_subprogram)
1722 {
1723 dw_addr_t hi_pc = DW_INVALID_ADDRESS;
1724 dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1725 if (lo_pc != DW_INVALID_ADDRESS)
1726 hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1727 if (hi_pc != DW_INVALID_ADDRESS)
1728 {
1729 // printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16llx - 0x%16.16llx)\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY
1730 debug_aranges->InsertRange(GetOffset(), lo_pc, hi_pc);
1731 }
1732 }
1733
1734 const DWARFDebugInfoEntry* child = GetFirstChild();
1735 while (child)
1736 {
1737 child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges);
1738 child = child->GetSibling();
1739 }
1740 }
1741}
1742
1743
1744//----------------------------------------------------------------------
1745// LookupAddress
1746//----------------------------------------------------------------------
1747bool
1748DWARFDebugInfoEntry::LookupAddress
1749(
1750 const dw_addr_t address,
1751 SymbolFileDWARF* dwarf2Data,
1752 const DWARFCompileUnit* cu,
1753 DWARFDebugInfoEntry** function_die,
1754 DWARFDebugInfoEntry** block_die
1755)
1756{
1757 bool found_address = false;
1758 if (m_abbrevDecl)
1759 {
1760 bool check_children = false;
1761 bool match_addr_range = false;
1762 dw_tag_t tag = m_abbrevDecl->Tag();
1763 // printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, DW_TAG_value_to_name(tag), address);
1764 switch (tag)
1765 {
1766 case DW_TAG_array_type : break;
1767 case DW_TAG_class_type : check_children = true; break;
1768 case DW_TAG_entry_point : break;
1769 case DW_TAG_enumeration_type : break;
1770 case DW_TAG_formal_parameter : break;
1771 case DW_TAG_imported_declaration : break;
1772 case DW_TAG_label : break;
1773 case DW_TAG_lexical_block : check_children = true; match_addr_range = true; break;
1774 case DW_TAG_member : break;
1775 case DW_TAG_pointer_type : break;
1776 case DW_TAG_reference_type : break;
1777 case DW_TAG_compile_unit : match_addr_range = true; break;
1778 case DW_TAG_string_type : break;
1779 case DW_TAG_structure_type : check_children = true; break;
1780 case DW_TAG_subroutine_type : break;
1781 case DW_TAG_typedef : break;
1782 case DW_TAG_union_type : break;
1783 case DW_TAG_unspecified_parameters : break;
1784 case DW_TAG_variant : break;
1785 case DW_TAG_common_block : check_children = true; break;
1786 case DW_TAG_common_inclusion : break;
1787 case DW_TAG_inheritance : break;
1788 case DW_TAG_inlined_subroutine : check_children = true; match_addr_range = true; break;
1789 case DW_TAG_module : match_addr_range = true; break;
1790 case DW_TAG_ptr_to_member_type : break;
1791 case DW_TAG_set_type : break;
1792 case DW_TAG_subrange_type : break;
1793 case DW_TAG_with_stmt : break;
1794 case DW_TAG_access_declaration : break;
1795 case DW_TAG_base_type : break;
1796 case DW_TAG_catch_block : match_addr_range = true; break;
1797 case DW_TAG_const_type : break;
1798 case DW_TAG_constant : break;
1799 case DW_TAG_enumerator : break;
1800 case DW_TAG_file_type : break;
1801 case DW_TAG_friend : break;
1802 case DW_TAG_namelist : break;
1803 case DW_TAG_namelist_item : break;
1804 case DW_TAG_packed_type : break;
1805 case DW_TAG_subprogram : match_addr_range = true; break;
1806 case DW_TAG_template_type_parameter : break;
1807 case DW_TAG_template_value_parameter : break;
1808 case DW_TAG_thrown_type : break;
1809 case DW_TAG_try_block : match_addr_range = true; break;
1810 case DW_TAG_variant_part : break;
1811 case DW_TAG_variable : break;
1812 case DW_TAG_volatile_type : break;
1813 case DW_TAG_dwarf_procedure : break;
1814 case DW_TAG_restrict_type : break;
1815 case DW_TAG_interface_type : break;
1816 case DW_TAG_namespace : check_children = true; break;
1817 case DW_TAG_imported_module : break;
1818 case DW_TAG_unspecified_type : break;
1819 case DW_TAG_partial_unit : break;
1820 case DW_TAG_imported_unit : break;
1821 case DW_TAG_shared_type : break;
1822 default: break;
1823 }
1824
1825 if (match_addr_range)
1826 {
1827 dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
1828 if (lo_pc != DW_INVALID_ADDRESS)
1829 {
1830 dw_addr_t hi_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
1831 if (hi_pc != DW_INVALID_ADDRESS)
1832 {
1833 // 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);
1834 if ((lo_pc <= address) && (address < hi_pc))
1835 {
1836 found_address = true;
1837 // puts("***MATCH***");
1838 switch (tag)
1839 {
1840 case DW_TAG_compile_unit: // File
1841 check_children = ((function_die != NULL) || (block_die != NULL));
1842 break;
1843
1844 case DW_TAG_subprogram: // Function
1845 if (function_die)
1846 *function_die = this;
1847 check_children = (block_die != NULL);
1848 break;
1849
1850 case DW_TAG_inlined_subroutine: // Inlined Function
1851 case DW_TAG_lexical_block: // Block { } in code
1852 if (block_die)
1853 {
1854 *block_die = this;
1855 check_children = true;
1856 }
1857 break;
1858
1859 default:
1860 check_children = true;
1861 break;
1862 }
1863 }
1864 }
1865 else
1866 { // compile units may not have a valid high/low pc when there
1867 // are address gaps in subtroutines so we must always search
1868 // if there is no valid high and low PC
1869 check_children = (tag == DW_TAG_compile_unit) && ((function_die != NULL) || (block_die != NULL));
1870 }
1871 }
1872 else
1873 {
1874 dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
1875 if (debug_ranges_offset != DW_INVALID_OFFSET)
1876 {
1877 DWARFDebugRanges::RangeList ranges;
1878 DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
1879 debug_ranges->FindRanges(debug_ranges_offset, ranges);
1880 // All DW_AT_ranges are relative to the base address of the
1881 // compile unit. We add the compile unit base address to make
1882 // sure all the addresses are properly fixed up.
1883 ranges.AddOffset(cu->GetBaseAddress());
1884 if (ranges.Lookup(address))
1885 {
1886 found_address = true;
1887 // puts("***MATCH***");
1888 switch (tag)
1889 {
1890 case DW_TAG_compile_unit: // File
1891 check_children = ((function_die != NULL) || (block_die != NULL));
1892 break;
1893
1894 case DW_TAG_subprogram: // Function
1895 if (function_die)
1896 *function_die = this;
1897 check_children = (block_die != NULL);
1898 break;
1899
1900 case DW_TAG_inlined_subroutine: // Inlined Function
1901 case DW_TAG_lexical_block: // Block { } in code
1902 if (block_die)
1903 {
1904 *block_die = this;
1905 check_children = true;
1906 }
1907 break;
1908
1909 default:
1910 check_children = true;
1911 break;
1912 }
1913 }
1914 else
1915 {
1916 check_children = false;
1917 }
1918 }
1919 }
1920 }
1921
1922
1923 if (check_children)
1924 {
1925 // printf("checking children\n");
1926 DWARFDebugInfoEntry* child = GetFirstChild();
1927 while (child)
1928 {
1929 if (child->LookupAddress(address, dwarf2Data, cu, function_die, block_die))
1930 return true;
1931 child = child->GetSibling();
1932 }
1933 }
1934 }
1935 return found_address;
1936}
1937
1938
1939bool
1940DWARFDebugInfoEntry::OffsetLessThan (const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b)
1941{
1942 return a.GetOffset() < b.GetOffset();
1943}
1944