DW_TAG_partial_unit) of this CU
"""
return self._get_DIE(0)
-
+
+ #------ PRIVATE ------#
+
def __getitem__(self, name):
""" Implement dict-like access to header entries
"""
return self._dielist[index]
def _parse_DIEs(self):
+ """ Parse all the DIEs pertaining to this CU from the stream and shove
+ them sequentially into self._dielist.
+ Also set the child/sibling/parent links in the DIEs according
+ (unflattening the prefix-order of the DIE tree).
+ """
# Compute the boundary (one byte past the bounds) of this CU in the
# stream
cu_boundary = ( self.cu_offset +
self['unit_length'] +
self.structs.initial_length_field_size())
+ # First pass: parse all DIEs and place them into self._dielist
die_offset = self.cu_die_offset
while die_offset < cu_boundary:
die = DIE(cu=self, stream=self.dwarfinfo.stream, offset=die_offset)
self._dielist.append(die)
die_offset += die.size
+ # Second pass - unflatten the DIE tree
+ self._unflatten_tree()
+
+ def _unflatten_tree(self):
+ """ "Unflatten" the DIE tree from it serial representation, by setting
+ the child/sibling/parent links of DIEs.
+
+ Assumes self._dielist was already populated by a linear list of DIEs
+ read from the stream section
+ """
+ # the first DIE in the list is the root node
+ root = self._dielist[0]
+ parentstack = [root]
+
+ for die in self._dielist[1:]:
+ if not die.is_null():
+ cur_parent = parentstack[-1]
+ # This DIE is a child of the current parent
+ cur_parent.add_child(die)
+ die.set_parent(cur_parent)
+ if die.has_children:
+ parentstack.append(die)
+ else:
+ # end of children for the current parent
+ parentstack.pop()
+
has_children:
Specifies whether this DIE has children
+
+ See also the public methods.
"""
def __init__(self, cu, stream, offset):
""" cu:
self.tag = None
self.has_children = None
self.size = 0
+ self._children = []
+ self._parent = None
self._parse_DIE()
"""
return self.tag is None
+ def get_parent(self):
+ """ The parent DIE of this DIE. None if the DIE has no parent (i.e. a
+ top-level DIE).
+ """
+ return self._parent
+
+ def iter_children(self):
+ """ Yield all children of this DIE
+ """
+ return iter(self._children)
+
+ def iter_siblings(self):
+ """ Yield all siblings of this DIE
+ """
+ if self._parent:
+ for sibling in self._parent.iter_children():
+ if sibling is not self:
+ yield sibling
+ else:
+ raise StopIteration()
+
+ # The following methods are used while creating the DIE and should not be
+ # interesting to consumers
+ #
+ def add_child(self, die):
+ self._children.append(die)
+
+ def set_parent(self, die):
+ self._parent = die
+
#------ PRIVATE ------#
+ def __repr__(self):
+ s = 'DIE %s, size=%s, has_chidren=%s\n' % (
+ self.tag, self.size, self.has_children)
+ for attrname, attrval in self.attributes.iteritems():
+ s += ' |%-18s: %s\n' % (attrname, attrval)
+ return s
+
+ def __str__(self):
+ return self.__repr__()
+
def _parse_DIE(self):
""" Parses the DIE info from the section, based on the abbreviation
table of the CU
print efile.has_dwarf_info()
dwarfinfo = efile.get_dwarf_info()
-tt = dwarfinfo.structs.Dwarf_dw_form['DW_FORM_block1'].parse('\x03\x12\x34\x46')
-cu = dwarfinfo.get_CU(1)
+cu = dwarfinfo.get_CU(3)
print 'CU header', cu.header
topdie = cu.get_top_DIE()
-for die in cu._dielist:
- print 'DIE %s, size=%s' % (die.tag, die.size)
- for attrname, val in die.attributes.iteritems():
- print ' ', attrname, val
+c = topdie.iter_children().next()
+
+print c
+
+print 'siblings.....'
+
+for s in c.iter_siblings():
+ print s
+
+#~ print c.get_parent()
+#~ print topdie
+
+#~ def recp(d, indent=0):
+ #~ s = str(d)
+ #~ lines = s.split('\n')
+ #~ print '\n'.join(' ' * indent + l for l in lines)
+
+ #~ for c in d.iter_children():
+ #~ recp(c, indent + 6)
+
+#~ recp(topdie)
+
+#~ for c in topdie.iter_children():
+ #~ print c
+#~ for die in cu._dielist:
+ #~ print 'DIE %s, size=%s' % (die.tag, die.size)
+ #~ for attrname, val in die.attributes.iteritems():
+ #~ print ' ', attrname, val
#~ topdie = cu.get_top_DIE()