1 #-------------------------------------------------------------------------------
2 # elftools: dwarf/die.py
4 # DWARF Debugging Information Entry
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
9 from collections
import namedtuple
11 from ..common
.ordereddict
import OrderedDict
12 from ..common
.utils
import struct_parse
, preserve_stream_pos
15 # AttributeValue - describes an attribute value in the DIE:
18 # The DW_FORM_* name of this attribute
21 # The value parsed from the section and translated accordingly to the form
22 # (e.g. for a DW_FORM_strp it's the actual string taken from the string table)
25 # Raw value as parsed from the section - used for debugging and presentation
26 # (e.g. for a DW_FORM_strp it's the raw string offset into the table)
28 AttributeValue
= namedtuple('AttributeValue', 'form value raw_value')
32 """ A DWARF debugging information entry. On creation, parses itself from
33 the stream. Each DIE is held by a CU.
35 Accessible attributes:
41 The size this DIE occupies in the section
44 An ordered dictionary mapping attribute names to values. It's
45 ordered to enable both efficient name->value mapping and
46 preserve the order of attributes in the section
49 Specifies whether this DIE has children
51 def __init__(self
, cu
, stream
, offset
):
53 CompileUnit object this DIE belongs to. Used to obtain context
54 information (structs, abbrev table, etc.)
57 The stream and offset into it where this DIE's data is located
60 self
.dwarfinfo
= self
.cu
.dwarfinfo
# get DWARFInfo context
63 self
.attributes
= OrderedDict()
67 """ Parses the DIE info from the section, based on the abbreviation
70 structs
= self
.cu
.structs
72 # A DIE begins with the abbreviation code. Read it and use it to
73 # obtain the abbrev declaration for this DIE.
74 # Note: here and elsewhere, preserve_stream_pos is used on operations
75 # that manipulate the stream by reading data from it.
77 abbrev_code
= struct_parse(
78 structs
.Dwarf_uleb128(''), self
.stream
, self
.offset
)
79 with
preserve_stream_pos(self
.stream
):
80 abbrev_decl
= self
.cu
.get_abbrev_table().get_abbrev(abbrev_code
)
81 self
.has_children
= abbrev_decl
.has_children()
83 # Guided by the attributes listed in the abbreviation declaration, parse
84 # values from the stream.
86 for name
, form
in abbrev_decl
.iter_attr_specs():
87 raw_value
= struct_parse(structs
.Dwarf_dw_form
[form
], self
.stream
)
88 value
= self
._translate
_attr
_value
(form
, raw_value
)
89 self
.attributes
[name
] = AttributeValue(form
, value
, raw_value
)
91 self
.size
= self
.stream
.tell() - self
.offset
93 def _translate_attr_value(self
, form
, raw_value
):
94 """ Translate a raw attr value according to the form
97 if form
== 'DW_FORM_strp':
98 with
preserve_stream_pos(self
.stream
):
99 value
= self
.dwarfinfo
.get_string_from_table(raw_value
)
100 elif form
== 'DW_FORM_flag':
101 value
= not raw_value
== 0
102 elif form
== 'DW_FORM_indirect':
104 raw_value
= struct_parse(
105 structs
.Dwarf_dw_form
[form
], self
.stream
)
106 # Let's hope this doesn't get too deep :-)
107 return self
._translate
_attr
_value
(form
, raw_value
)