# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
-from collections import namedtuple
+from collections import namedtuple, OrderedDict
import os
-from ..common.py3compat import OrderedDict, bytes2str, iteritems
+from ..common.exceptions import DWARFError
+from ..common.py3compat import bytes2str, iteritems
from ..common.utils import struct_parse, preserve_stream_pos
+from .enums import DW_FORM_raw2name
# AttributeValue - describes an attribute value in the DIE:
#------ PRIVATE ------#
def __repr__(self):
- s = 'DIE %s, size=%s, has_chidren=%s\n' % (
+ s = 'DIE %s, size=%s, has_children=%s\n' % (
self.tag, self.size, self.has_children)
for attrname, attrval in iteritems(self.attributes):
s += ' |%-18s: %s\n' % (attrname, attrval)
# obtain the abbrev declaration for this DIE.
# Note: here and elsewhere, preserve_stream_pos is used on operations
# that manipulate the stream by reading data from it.
- #
self.abbrev_code = struct_parse(
structs.Dwarf_uleb128(''), self.stream, self.offset)
# Guided by the attributes listed in the abbreviation declaration, parse
# values from the stream.
- #
for name, form in abbrev_decl.iter_attr_specs():
attr_offset = self.stream.tell()
raw_value = struct_parse(structs.Dwarf_dw_form[form], self.stream)
raw_value=raw_value,
offset=attr_offset)
+ # Count and then consume any null termination bytes to avoid wrong die
+ # size calculation.
+ num_zero_terminators = 0
+ with preserve_stream_pos(self.stream):
+ while True:
+ if self.stream.read(1) == 0:
+ num_zero_terminators += 1
+ else:
+ break
+ if num_zero_terminators > 0:
+ # There was at least one zero termination -> consume all of them.
+ self.stream.read(num_zero_terminators)
+
self.size = self.stream.tell() - self.offset
def _translate_attr_value(self, form, raw_value):
elif form == 'DW_FORM_flag':
value = not raw_value == 0
elif form == 'DW_FORM_indirect':
- form = raw_value
+ try:
+ form = DW_FORM_raw2name[raw_value]
+ except KeyError as err:
+ raise DWARFError(
+ 'Found DW_FORM_indirect with unknown raw_value=' +
+ str(raw_value))
+
raw_value = struct_parse(
- structs.Dwarf_dw_form[form], self.stream)
+ self.cu.structs.Dwarf_dw_form[form], self.stream)
# Let's hope this doesn't get too deep :-)
return self._translate_attr_value(form, raw_value)
else: