ad818920c7c9650ee2e81c0ce710e9b218f77db8
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)
29 # Offset of this attribute's value in the stream
31 AttributeValue
= namedtuple(
32 'AttributeValue', 'form value raw_value offset')
36 """ A DWARF debugging information entry. On creation, parses itself from
37 the stream. Each DIE is held by a CU.
39 Accessible attributes:
45 The size this DIE occupies in the section
48 The offset of this DIE in the stream
51 An ordered dictionary mapping attribute names to values. It's
52 ordered to enable both efficient name->value mapping and
53 preserve the order of attributes in the section
56 Specifies whether this DIE has children
59 The abbreviation code pointing to an abbreviation entry (not
60 that this is for informational pusposes only - this object
61 interacts with its abbreviation table transparently).
63 See also the public methods.
65 def __init__(self
, cu
, stream
, offset
):
67 CompileUnit object this DIE belongs to. Used to obtain context
68 information (structs, abbrev table, etc.)
71 The stream and offset into it where this DIE's data is located
74 self
.dwarfinfo
= self
.cu
.dwarfinfo
# get DWARFInfo context
78 self
.attributes
= OrderedDict()
80 self
.has_children
= None
81 self
.abbrev_code
= None
89 """ Is this a null entry?
91 return self
.tag
is None
94 """ The parent DIE of this DIE. None if the DIE has no parent (i.e. a
99 def iter_children(self
):
100 """ Yield all children of this DIE
102 return iter(self
._children
)
104 def iter_siblings(self
):
105 """ Yield all siblings of this DIE
108 for sibling
in self
._parent
.iter_children():
109 if sibling
is not self
:
112 raise StopIteration()
114 # The following methods are used while creating the DIE and should not be
115 # interesting to consumers
117 def add_child(self
, die
):
118 self
._children
.append(die
)
120 def set_parent(self
, die
):
123 #------ PRIVATE ------#
126 s
= 'DIE %s, size=%s, has_chidren=%s\n' % (
127 self
.tag
, self
.size
, self
.has_children
)
128 for attrname
, attrval
in self
.attributes
.iteritems():
129 s
+= ' |%-18s: %s\n' % (attrname
, attrval
)
133 return self
.__repr
__()
135 def _parse_DIE(self
):
136 """ Parses the DIE info from the section, based on the abbreviation
139 structs
= self
.cu
.structs
141 # A DIE begins with the abbreviation code. Read it and use it to
142 # obtain the abbrev declaration for this DIE.
143 # Note: here and elsewhere, preserve_stream_pos is used on operations
144 # that manipulate the stream by reading data from it.
146 self
.abbrev_code
= struct_parse(
147 structs
.Dwarf_uleb128(''), self
.stream
, self
.offset
)
149 # This may be a null entry
150 if self
.abbrev_code
== 0:
151 self
.size
= self
.stream
.tell() - self
.offset
154 with
preserve_stream_pos(self
.stream
):
155 abbrev_decl
= self
.cu
.get_abbrev_table().get_abbrev(
157 self
.tag
= abbrev_decl
['tag']
158 self
.has_children
= abbrev_decl
.has_children()
160 # Guided by the attributes listed in the abbreviation declaration, parse
161 # values from the stream.
163 for name
, form
in abbrev_decl
.iter_attr_specs():
164 attr_offset
= self
.stream
.tell()
165 raw_value
= struct_parse(structs
.Dwarf_dw_form
[form
], self
.stream
)
166 value
= self
._translate
_attr
_value
(form
, raw_value
)
167 self
.attributes
[name
] = AttributeValue(
173 self
.size
= self
.stream
.tell() - self
.offset
175 def _translate_attr_value(self
, form
, raw_value
):
176 """ Translate a raw attr value according to the form
179 if form
== 'DW_FORM_strp':
180 with
preserve_stream_pos(self
.stream
):
181 value
= self
.dwarfinfo
.get_string_from_table(raw_value
)
182 elif form
== 'DW_FORM_flag':
183 value
= not raw_value
== 0
184 elif form
== 'DW_FORM_indirect':
186 raw_value
= struct_parse(
187 structs
.Dwarf_dw_form
[form
], self
.stream
)
188 # Let's hope this doesn't get too deep :-)
189 return self
._translate
_attr
_value
(form
, raw_value
)